|
From: <ls...@us...> - 2007-05-13 17:11:30
|
Revision: 3200
http://jnode.svn.sourceforge.net/jnode/?rev=3200&view=rev
Author: lsantha
Date: 2007-05-13 10:11:27 -0700 (Sun, 13 May 2007)
Log Message:
-----------
First merges of OpenJDK.
Added Paths:
-----------
trunk/core/src/openjdk/sun/sun/misc/
trunk/core/src/openjdk/sun/sun/misc/DoubleConsts.java
trunk/core/src/openjdk/sun/sun/misc/FloatConsts.java
trunk/core/src/openjdk/sun/sun/misc/FloatingDecimal.java
trunk/core/src/openjdk/sun/sun/misc/FpUtils.java
trunk/core/src/openjdk/sun/sun/text/
trunk/core/src/openjdk/sun/sun/text/Normalizer.java
trunk/core/src/openjdk/sun/sun/text/normalizer/
trunk/core/src/openjdk/sun/sun/text/normalizer/CharTrie.java
trunk/core/src/openjdk/sun/sun/text/normalizer/CharacterIteratorWrapper.java
trunk/core/src/openjdk/sun/sun/text/normalizer/ICUBinary.java
trunk/core/src/openjdk/sun/sun/text/normalizer/ICUData.java
trunk/core/src/openjdk/sun/sun/text/normalizer/IntTrie.java
trunk/core/src/openjdk/sun/sun/text/normalizer/NormalizerBase.java
trunk/core/src/openjdk/sun/sun/text/normalizer/NormalizerDataReader.java
trunk/core/src/openjdk/sun/sun/text/normalizer/NormalizerImpl.java
trunk/core/src/openjdk/sun/sun/text/normalizer/RangeValueIterator.java
trunk/core/src/openjdk/sun/sun/text/normalizer/Replaceable.java
trunk/core/src/openjdk/sun/sun/text/normalizer/ReplaceableString.java
trunk/core/src/openjdk/sun/sun/text/normalizer/ReplaceableUCharacterIterator.java
trunk/core/src/openjdk/sun/sun/text/normalizer/RuleCharacterIterator.java
trunk/core/src/openjdk/sun/sun/text/normalizer/SymbolTable.java
trunk/core/src/openjdk/sun/sun/text/normalizer/Trie.java
trunk/core/src/openjdk/sun/sun/text/normalizer/TrieIterator.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UCharacter.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UCharacterIterator.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UCharacterProperty.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UCharacterPropertyReader.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UProperty.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UTF16.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UnicodeMatcher.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UnicodeSet.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UnicodeSetIterator.java
trunk/core/src/openjdk/sun/sun/text/normalizer/Utility.java
trunk/core/src/openjdk/sun/sun/text/normalizer/VersionInfo.java
Added: trunk/core/src/openjdk/sun/sun/misc/DoubleConsts.java
===================================================================
--- trunk/core/src/openjdk/sun/sun/misc/DoubleConsts.java (rev 0)
+++ trunk/core/src/openjdk/sun/sun/misc/DoubleConsts.java 2007-05-13 17:11:27 UTC (rev 3200)
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.misc;
+
+/**
+ * This class contains additional constants documenting limits of the
+ * <code>double</code> type.
+ *
+ * @author Joseph D. Darcy
+ * @version 1.7, 05/05/07
+ */
+
+public class DoubleConsts {
+ /**
+ * Don't let anyone instantiate this class.
+ */
+ private DoubleConsts() {}
+
+ public static final double POSITIVE_INFINITY = java.lang.Double.POSITIVE_INFINITY;
+ public static final double NEGATIVE_INFINITY = java.lang.Double.NEGATIVE_INFINITY;
+ public static final double NaN = java.lang.Double.NaN;
+ public static final double MAX_VALUE = java.lang.Double.MAX_VALUE;
+ public static final double MIN_VALUE = java.lang.Double.MIN_VALUE;
+
+ /**
+ * A constant holding the smallest positive normal value of type
+ * <code>double</code>, 2<sup>-1022</sup>. It is equal to the
+ * value returned by
+ * <code>Double.longBitsToDouble(0x0010000000000000L)</code>.
+ *
+ * @since 1.5
+ */
+ public static final double MIN_NORMAL = 2.2250738585072014E-308;
+
+
+ /**
+ * The number of logical bits in the significand of a
+ * <code>double</code> number, including the implicit bit.
+ */
+ public static final int SIGNIFICAND_WIDTH = 53;
+
+ /**
+ * Maximum exponent a finite <code>double</code> number may have.
+ * It is equal to the value returned by
+ * <code>Math.ilogb(Double.MAX_VALUE)</code>.
+ */
+ public static final int MAX_EXPONENT = 1023;
+
+ /**
+ * Minimum exponent a normalized <code>double</code> number may
+ * have. It is equal to the value returned by
+ * <code>Math.ilogb(Double.MIN_NORMAL)</code>.
+ */
+ public static final int MIN_EXPONENT = -1022;
+
+ /**
+ * The exponent the smallest positive <code>double</code>
+ * subnormal value would have if it could be normalized. It is
+ * equal to the value returned by
+ * <code>FpUtils.ilogb(Double.MIN_VALUE)</code>.
+ */
+ public static final int MIN_SUB_EXPONENT = MIN_EXPONENT -
+ (SIGNIFICAND_WIDTH - 1);
+
+ /**
+ * Bias used in representing a <code>double</code> exponent.
+ */
+ public static final int EXP_BIAS = 1023;
+
+ /**
+ * Bit mask to isolate the sign bit of a <code>double</code>.
+ */
+ public static final long SIGN_BIT_MASK = 0x8000000000000000L;
+
+ /**
+ * Bit mask to isolate the exponent field of a
+ * <code>double</code>.
+ */
+ public static final long EXP_BIT_MASK = 0x7FF0000000000000L;
+
+ /**
+ * Bit mask to isolate the significand field of a
+ * <code>double</code>.
+ */
+ public static final long SIGNIF_BIT_MASK = 0x000FFFFFFFFFFFFFL;
+
+ static {
+ // verify bit masks cover all bit positions and that the bit
+ // masks are non-overlapping
+ assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0L) &&
+ (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0L) &&
+ ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0L) &&
+ ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0L)));
+ }
+}
Added: trunk/core/src/openjdk/sun/sun/misc/FloatConsts.java
===================================================================
--- trunk/core/src/openjdk/sun/sun/misc/FloatConsts.java (rev 0)
+++ trunk/core/src/openjdk/sun/sun/misc/FloatConsts.java 2007-05-13 17:11:27 UTC (rev 3200)
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.misc;
+
+/**
+ * This class contains additional constants documenting limits of the
+ * <code>float</code> type.
+ *
+ * @author Joseph D. Darcy
+ * @version 1.7, 05/05/07
+ */
+
+public class FloatConsts {
+ /**
+ * Don't let anyone instantiate this class.
+ */
+ private FloatConsts() {}
+
+ public static final float POSITIVE_INFINITY = java.lang.Float.POSITIVE_INFINITY;
+ public static final float NEGATIVE_INFINITY = java.lang.Float.NEGATIVE_INFINITY;
+ public static final float NaN = java.lang.Float.NaN;
+ public static final float MAX_VALUE = java.lang.Float.MAX_VALUE;
+ public static final float MIN_VALUE = java.lang.Float.MIN_VALUE;
+
+ /**
+ * A constant holding the smallest positive normal value of type
+ * <code>float</code>, 2<sup>-126</sup>. It is equal to the value
+ * returned by <code>Float.intBitsToFloat(0x00800000)</code>.
+ */
+ public static final float MIN_NORMAL = 1.17549435E-38f;
+
+ /**
+ * The number of logical bits in the significand of a
+ * <code>float</code> number, including the implicit bit.
+ */
+ public static final int SIGNIFICAND_WIDTH = 24;
+
+ /**
+ * Maximum exponent a finite <code>float</code> number may have.
+ * It is equal to the value returned by
+ * <code>Math.ilogb(Float.MAX_VALUE)</code>.
+ */
+ public static final int MAX_EXPONENT = 127;
+
+ /**
+ * Minimum exponent a normalized <code>float</code> number may
+ * have. It is equal to the value returned by
+ * <code>Math.ilogb(Float.MIN_NORMAL)</code>.
+ */
+ public static final int MIN_EXPONENT = -126;
+
+ /**
+ * The exponent the smallest positive <code>float</code> subnormal
+ * value would have if it could be normalized. It is equal to the
+ * value returned by <code>FpUtils.ilogb(Float.MIN_VALUE)</code>.
+ */
+ public static final int MIN_SUB_EXPONENT = MIN_EXPONENT -
+ (SIGNIFICAND_WIDTH - 1);
+
+ /**
+ * Bias used in representing a <code>float</code> exponent.
+ */
+ public static final int EXP_BIAS = 127;
+
+ /**
+ * Bit mask to isolate the sign bit of a <code>float</code>.
+ */
+ public static final int SIGN_BIT_MASK = 0x80000000;
+
+ /**
+ * Bit mask to isolate the exponent field of a
+ * <code>float</code>.
+ */
+ public static final int EXP_BIT_MASK = 0x7F800000;
+
+ /**
+ * Bit mask to isolate the significand field of a
+ * <code>float</code>.
+ */
+ public static final int SIGNIF_BIT_MASK = 0x007FFFFF;
+
+ static {
+ // verify bit masks cover all bit positions and that the bit
+ // masks are non-overlapping
+ assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0) &&
+ (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0) &&
+ ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0) &&
+ ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0)));
+ }
+}
Added: trunk/core/src/openjdk/sun/sun/misc/FloatingDecimal.java
===================================================================
--- trunk/core/src/openjdk/sun/sun/misc/FloatingDecimal.java (rev 0)
+++ trunk/core/src/openjdk/sun/sun/misc/FloatingDecimal.java 2007-05-13 17:11:27 UTC (rev 3200)
@@ -0,0 +1,2876 @@
+/*
+ * Copyright 1996-2004 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.misc;
+
+import sun.misc.FpUtils;
+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
+
+ 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.
+ * 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 = (char[])(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 = (char[])(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);
+ }
+
+ /*
+ * 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 = (int)( (fBits&singleExpMask) >> singleExpShift );
+ fractBits = fBits&singleFractMask;
+ if ( binExp == (int)(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 = (int) ( b / s );
+ b = 10 * ( b % s );
+ m *= 10;
+ low = (b < m );
+ high = (b+m > tens );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ /*
+ * HACK! Java spec sez that we always have at least
+ * one digit after the . in either F- or E-form output.
+ * Thus we will need more than one digit if we're using
+ * E-form
+ */
+ if ( decExp <= -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = (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 {
+ // still good! they're all longs!
+ long b = (fractBits * long5pow[B5] ) << B2;
+ long s = long5pow[S5] << S2;
+ long m = long5pow[M5] << M2;
+ long tens = s * 10L;
+ /*
+ * Unroll the first iteration. If our decExp estimate
+ * was too high, our first quotient will be zero. In this
+ * case, we discard it and decrement decExp.
+ */
+ ndigit = 0;
+ q = (int) ( b / s );
+ b = 10L * ( b % s );
+ m *= 10L;
+ low = (b < m );
+ high = (b+m > tens );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ /*
+ * HACK! Java spec sez that we always have at least
+ * one digit after the . in either F- or E-form output.
+ * Thus we will need more than one digit if we're using
+ * E-form
+ */
+ if ( decExp <= -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = (int) ( b / s );
+ b = 10 * ( b % s );
+ m *= 10;
+ assert q < 10 : q; // excessively large digit
+ if ( m > 0L ){
+ low = (b < m );
+ high = (b+m > tens );
+ } else {
+ // hack -- m might overflow!
+ // in this case, it is certainly > b,
+ // which won't
+ // and b+m > tens, too, since that has overflowed
+ // either!
+ low = true;
+ high = true;
+ }
+ digits[ndigit++] = (char)('0' + q);
+ }
+ lowDigitDifference = (b<<1) - tens;
+ }
+ } 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 ( 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!
+ }
+ 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);
+ }
+
+ public String toJavaFormatString() {
+ char result[] = (char[])(perThreadBuffer.get());
+ int i = getChars(result);
+ return new String(result, 0, i);
+ }
+
+ private int getChars(char[] result) {
+ assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
+ int i = 0;
+ if (isNegative) { result[0] = '-'; i = 1; }
+ if (isExceptional) {
+ System.arraycopy(digits, 0, result, i, nDigits);
+ i += nDigits;
+ } else {
+ if (decExponent > 0 && decExponent < 8) {
+ // print digits.digits.
+ int charLength = Math.min(nDigits, decExponent);
+ System.arraycopy(digits, 0, result, i, charLength);
+ i += charLength;
+ if (charLength < decExponent) {
+ charLength = decExponent-charLength;
+ System.arraycopy(zero, 0, result, i, charLength);
+ i += charLength;
+ result[i++] = '.';
+ result[i++] = '0';
+ } else {
+ result[i++] = '.';
+ if (charLength < nDigits) {
+ int t = nDigits - charLength;
+ System.arraycopy(digits, charLength, result, i, t);
+ i += t;
+ } else {
+ result[i++] = '0';
+ }
+ }
+ } else if (decExponent <=0 && decExponent > -3) {
+ result[i++] = '0';
+ result[i++] = '.';
+ if (decExponent != 0) {
+ System.arraycopy(zero, 0, result, i, -decExponent);
+ i -= decExponent;
+ }
+ System.arraycopy(digits, 0, result, i, nDigits);
+ i += nDigits;
+ } else {
+ result[i++] = digits[0];
+ result[i++] = '.';
+ if (nDigits > 1) {
+ System.arraycopy(digits, 1, result, i, nDigits-1);
+ i += nDigits-1;
+ } else {
+ result[i++] = '0';
+ }
+ result[i++] = 'E';
+ int e;
+ if (decExponent <= 0) {
+ result[i++] = '-';
+ e = -decExponent+1;
+ } else {
+ e = decExponent-1;
+ }
+ // decExponent has 1, 2, or 3, digits
+ if (e <= 9) {
+ result[i++] = (char)(e+'0');
+ } else if (e <= 99) {
+ result[i++] = (char)(e/10 +'0');
+ result[i++] = (char)(e%10 + '0');
+ } else {
+ result[i++] = (char)(e/100+'0');
+ e %= 100;
+ result[i++] = (char)(e/10+'0');
+ result[i++] = (char)(e%10 + '0');
+ }
+ }
+ }
+ return i;
+ }
+
+ // Per-thread buffer for string/stringbuffer conversion
+ private static ThreadLocal perThreadBuffer = new ThreadLocal() {
+ protected synchronized Object initialValue() {
+ return new char[26];
+ }
+ };
+
+ public void appendTo(Appendable buf) {
+ char result[] = (char[])(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;
+ }
+
+ 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 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
+ // 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 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 i...
[truncated message content] |