8145990: Move sun.misc math support classes to jdk.internal.math
Reviewed-by: bpb, darcy
--- a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Tue Dec 22 11:07:17 2015 +0800
+++ b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Tue Dec 22 12:17:25 2015 +0000
@@ -25,7 +25,7 @@
package java.lang;
-import sun.misc.FloatingDecimal;
+import jdk.internal.math.FloatingDecimal;
import java.util.Arrays;
import java.util.Spliterator;
import java.util.stream.IntStream;
--- a/jdk/src/java.base/share/classes/java/lang/Double.java Tue Dec 22 11:07:17 2015 +0800
+++ b/jdk/src/java.base/share/classes/java/lang/Double.java Tue Dec 22 12:17:25 2015 +0000
@@ -25,8 +25,8 @@
package java.lang;
-import sun.misc.FloatingDecimal;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.FloatingDecimal;
+import jdk.internal.math.DoubleConsts;
import jdk.internal.HotSpotIntrinsicCandidate;
/**
--- a/jdk/src/java.base/share/classes/java/lang/Float.java Tue Dec 22 11:07:17 2015 +0800
+++ b/jdk/src/java.base/share/classes/java/lang/Float.java Tue Dec 22 12:17:25 2015 +0000
@@ -25,9 +25,9 @@
package java.lang;
-import sun.misc.FloatingDecimal;
-import sun.misc.FloatConsts;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.FloatingDecimal;
+import jdk.internal.math.FloatConsts;
+import jdk.internal.math.DoubleConsts;
import jdk.internal.HotSpotIntrinsicCandidate;
/**
--- a/jdk/src/java.base/share/classes/java/lang/Math.java Tue Dec 22 11:07:17 2015 +0800
+++ b/jdk/src/java.base/share/classes/java/lang/Math.java Tue Dec 22 12:17:25 2015 +0000
@@ -26,8 +26,8 @@
package java.lang;
import java.util.Random;
-import sun.misc.FloatConsts;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.FloatConsts;
+import jdk.internal.math.DoubleConsts;
import jdk.internal.HotSpotIntrinsicCandidate;
/**
--- a/jdk/src/java.base/share/classes/java/lang/StrictMath.java Tue Dec 22 11:07:17 2015 +0800
+++ b/jdk/src/java.base/share/classes/java/lang/StrictMath.java Tue Dec 22 12:17:25 2015 +0000
@@ -26,7 +26,7 @@
package java.lang;
import java.util.Random;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.DoubleConsts;
import jdk.internal.HotSpotIntrinsicCandidate;
/**
--- a/jdk/src/java.base/share/classes/java/math/BigInteger.java Tue Dec 22 11:07:17 2015 +0800
+++ b/jdk/src/java.base/share/classes/java/math/BigInteger.java Tue Dec 22 12:17:25 2015 +0000
@@ -38,8 +38,8 @@
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
-import sun.misc.DoubleConsts;
-import sun.misc.FloatConsts;
+import jdk.internal.math.DoubleConsts;
+import jdk.internal.math.FloatConsts;
import jdk.internal.HotSpotIntrinsicCandidate;
/**
--- a/jdk/src/java.base/share/classes/java/text/DigitList.java Tue Dec 22 11:07:17 2015 +0800
+++ b/jdk/src/java.base/share/classes/java/text/DigitList.java Tue Dec 22 12:17:25 2015 +0000
@@ -41,7 +41,7 @@
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
-import sun.misc.FloatingDecimal;
+import jdk.internal.math.FloatingDecimal;
/**
* Digit List. Private to DecimalFormat.
--- a/jdk/src/java.base/share/classes/java/util/Formatter.java Tue Dec 22 11:07:17 2015 +0800
+++ b/jdk/src/java.base/share/classes/java/util/Formatter.java Tue Dec 22 12:17:25 2015 +0000
@@ -60,8 +60,8 @@
import java.time.temporal.TemporalQueries;
import java.time.temporal.UnsupportedTemporalTypeException;
-import sun.misc.DoubleConsts;
-import sun.misc.FormattedFloatingDecimal;
+import jdk.internal.math.DoubleConsts;
+import jdk.internal.math.FormattedFloatingDecimal;
/**
* An interpreter for printf-style format strings. This class provides support
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/math/DoubleConsts.java Tue Dec 22 12:17:25 2015 +0000
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.math;
+
+/**
+ * This class contains additional constants documenting limits of the
+ * <code>double</code> type.
+ *
+ * @author Joseph D. Darcy
+ */
+
+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..
+ */
+ 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)));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/math/FDBigInteger.java Tue Dec 22 12:17:25 2015 +0000
@@ -0,0 +1,1508 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.math;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+//@ model import org.jmlspecs.models.JMLMath;
+
+/**
+ * A simple big integer package specifically for floating point base conversion.
+ */
+public /*@ spec_bigint_math @*/ class FDBigInteger {
+
+ //
+ // This class contains many comments that start with "/*@" mark.
+ // They are behavourial specification in
+ // the Java Modelling Language (JML):
+ // http://www.eecs.ucf.edu/~leavens/JML//index.shtml
+ //
+
+ /*@
+ @ public pure model static \bigint UNSIGNED(int v) {
+ @ return v >= 0 ? v : v + (((\bigint)1) << 32);
+ @ }
+ @
+ @ public pure model static \bigint UNSIGNED(long v) {
+ @ return v >= 0 ? v : v + (((\bigint)1) << 64);
+ @ }
+ @
+ @ public pure model static \bigint AP(int[] data, int len) {
+ @ return (\sum int i; 0 <= 0 && i < len; UNSIGNED(data[i]) << (i*32));
+ @ }
+ @
+ @ public pure model static \bigint pow52(int p5, int p2) {
+ @ ghost \bigint v = 1;
+ @ for (int i = 0; i < p5; i++) v *= 5;
+ @ return v << p2;
+ @ }
+ @
+ @ public pure model static \bigint pow10(int p10) {
+ @ return pow52(p10, p10);
+ @ }
+ @*/
+
+ static final int[] SMALL_5_POW = {
+ 1,
+ 5,
+ 5 * 5,
+ 5 * 5 * 5,
+ 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
+ };
+
+ static final long[] LONG_5_POW = {
+ 1L,
+ 5L,
+ 5L * 5,
+ 5L * 5 * 5,
+ 5L * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ };
+
+ // Maximum size of cache of powers of 5 as FDBigIntegers.
+ private static final int MAX_FIVE_POW = 340;
+
+ // Cache of big powers of 5 as FDBigIntegers.
+ private static final FDBigInteger POW_5_CACHE[];
+
+ // Initialize FDBigInteger cache of powers of 5.
+ static {
+ POW_5_CACHE = new FDBigInteger[MAX_FIVE_POW];
+ int i = 0;
+ while (i < SMALL_5_POW.length) {
+ FDBigInteger pow5 = new FDBigInteger(new int[]{SMALL_5_POW[i]}, 0);
+ pow5.makeImmutable();
+ POW_5_CACHE[i] = pow5;
+ i++;
+ }
+ FDBigInteger prev = POW_5_CACHE[i - 1];
+ while (i < MAX_FIVE_POW) {
+ POW_5_CACHE[i] = prev = prev.mult(5);
+ prev.makeImmutable();
+ i++;
+ }
+ }
+
+ // Zero as an FDBigInteger.
+ public static final FDBigInteger ZERO = new FDBigInteger(new int[0], 0);
+
+ // Ensure ZERO is immutable.
+ static {
+ ZERO.makeImmutable();
+ }
+
+ // Constant for casting an int to a long via bitwise AND.
+ private static final long LONG_MASK = 0xffffffffL;
+
+ //@ spec_public non_null;
+ private int data[]; // value: data[0] is least significant
+ //@ spec_public;
+ private int offset; // number of least significant zero padding ints
+ //@ spec_public;
+ private int nWords; // data[nWords-1]!=0, all values above are zero
+ // if nWords==0 -> this FDBigInteger is zero
+ //@ spec_public;
+ private boolean isImmutable = false;
+
+ /*@
+ @ public invariant 0 <= nWords && nWords <= data.length && offset >= 0;
+ @ public invariant nWords == 0 ==> offset == 0;
+ @ public invariant nWords > 0 ==> data[nWords - 1] != 0;
+ @ public invariant (\forall int i; nWords <= i && i < data.length; data[i] == 0);
+ @ public pure model \bigint value() {
+ @ return AP(data, nWords) << (offset*32);
+ @ }
+ @*/
+
+ /**
+ * Constructs an <code>FDBigInteger</code> from data and padding. The
+ * <code>data</code> parameter has the least significant <code>int</code> at
+ * the zeroth index. The <code>offset</code> parameter gives the number of
+ * zero <code>int</code>s to be inferred below the least significant element
+ * of <code>data</code>.
+ *
+ * @param data An array containing all non-zero <code>int</code>s of the value.
+ * @param offset An offset indicating the number of zero <code>int</code>s to pad
+ * below the least significant element of <code>data</code>.
+ */
+ /*@
+ @ requires data != null && offset >= 0;
+ @ ensures this.value() == \old(AP(data, data.length) << (offset*32));
+ @ ensures this.data == \old(data);
+ @*/
+ private FDBigInteger(int[] data, int offset) {
+ this.data = data;
+ this.offset = offset;
+ this.nWords = data.length;
+ trimLeadingZeros();
+ }
+
+ /**
+ * Constructs an <code>FDBigInteger</code> from a starting value and some
+ * decimal digits.
+ *
+ * @param lValue The starting value.
+ * @param digits The decimal digits.
+ * @param kDigits The initial index into <code>digits</code>.
+ * @param nDigits The final index into <code>digits</code>.
+ */
+ /*@
+ @ requires digits != null;
+ @ requires 0 <= kDigits && kDigits <= nDigits && nDigits <= digits.length;
+ @ requires (\forall int i; 0 <= i && i < nDigits; '0' <= digits[i] && digits[i] <= '9');
+ @ ensures this.value() == \old(lValue * pow10(nDigits - kDigits) + (\sum int i; kDigits <= i && i < nDigits; (digits[i] - '0') * pow10(nDigits - i - 1)));
+ @*/
+ public FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits) {
+ int n = Math.max((nDigits + 8) / 9, 2); // estimate size needed.
+ data = new int[n]; // allocate enough space
+ data[0] = (int) lValue; // starting value
+ data[1] = (int) (lValue >>> 32);
+ offset = 0;
+ nWords = 2;
+ int i = kDigits;
+ int limit = nDigits - 5; // slurp digits 5 at a time.
+ int v;
+ while (i < limit) {
+ int ilim = i + 5;
+ v = (int) digits[i++] - (int) '0';
+ while (i < ilim) {
+ v = 10 * v + (int) digits[i++] - (int) '0';
+ }
+ multAddMe(100000, v); // ... where 100000 is 10^5.
+ }
+ int factor = 1;
+ v = 0;
+ while (i < nDigits) {
+ v = 10 * v + (int) digits[i++] - (int) '0';
+ factor *= 10;
+ }
+ if (factor != 1) {
+ multAddMe(factor, v);
+ }
+ trimLeadingZeros();
+ }
+
+ /**
+ * Returns an <code>FDBigInteger</code> with the numerical value
+ * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
+ *
+ * @param p5 The exponent of the power-of-five factor.
+ * @param p2 The exponent of the power-of-two factor.
+ * @return <code>5<sup>p5</sup> * 2<sup>p2</sup></code>
+ */
+ /*@
+ @ requires p5 >= 0 && p2 >= 0;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(pow52(p5, p2));
+ @*/
+ public static FDBigInteger valueOfPow52(int p5, int p2) {
+ if (p5 != 0) {
+ if (p2 == 0) {
+ return big5pow(p5);
+ } else if (p5 < SMALL_5_POW.length) {
+ int pow5 = SMALL_5_POW[p5];
+ int wordcount = p2 >> 5;
+ int bitcount = p2 & 0x1f;
+ if (bitcount == 0) {
+ return new FDBigInteger(new int[]{pow5}, wordcount);
+ } else {
+ return new FDBigInteger(new int[]{
+ pow5 << bitcount,
+ pow5 >>> (32 - bitcount)
+ }, wordcount);
+ }
+ } else {
+ return big5pow(p5).leftShift(p2);
+ }
+ } else {
+ return valueOfPow2(p2);
+ }
+ }
+
+ /**
+ * Returns an <code>FDBigInteger</code> with the numerical value
+ * <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>.
+ *
+ * @param value The constant factor.
+ * @param p5 The exponent of the power-of-five factor.
+ * @param p2 The exponent of the power-of-two factor.
+ * @return <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>
+ */
+ /*@
+ @ requires p5 >= 0 && p2 >= 0;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(UNSIGNED(value) * pow52(p5, p2));
+ @*/
+ public static FDBigInteger valueOfMulPow52(long value, int p5, int p2) {
+ assert p5 >= 0 : p5;
+ assert p2 >= 0 : p2;
+ int v0 = (int) value;
+ int v1 = (int) (value >>> 32);
+ int wordcount = p2 >> 5;
+ int bitcount = p2 & 0x1f;
+ if (p5 != 0) {
+ if (p5 < SMALL_5_POW.length) {
+ long pow5 = SMALL_5_POW[p5] & LONG_MASK;
+ long carry = (v0 & LONG_MASK) * pow5;
+ v0 = (int) carry;
+ carry >>>= 32;
+ carry = (v1 & LONG_MASK) * pow5 + carry;
+ v1 = (int) carry;
+ int v2 = (int) (carry >>> 32);
+ if (bitcount == 0) {
+ return new FDBigInteger(new int[]{v0, v1, v2}, wordcount);
+ } else {
+ return new FDBigInteger(new int[]{
+ v0 << bitcount,
+ (v1 << bitcount) | (v0 >>> (32 - bitcount)),
+ (v2 << bitcount) | (v1 >>> (32 - bitcount)),
+ v2 >>> (32 - bitcount)
+ }, wordcount);
+ }
+ } else {
+ FDBigInteger pow5 = big5pow(p5);
+ int[] r;
+ if (v1 == 0) {
+ r = new int[pow5.nWords + 1 + ((p2 != 0) ? 1 : 0)];
+ mult(pow5.data, pow5.nWords, v0, r);
+ } else {
+ r = new int[pow5.nWords + 2 + ((p2 != 0) ? 1 : 0)];
+ mult(pow5.data, pow5.nWords, v0, v1, r);
+ }
+ return (new FDBigInteger(r, pow5.offset)).leftShift(p2);
+ }
+ } else if (p2 != 0) {
+ if (bitcount == 0) {
+ return new FDBigInteger(new int[]{v0, v1}, wordcount);
+ } else {
+ return new FDBigInteger(new int[]{
+ v0 << bitcount,
+ (v1 << bitcount) | (v0 >>> (32 - bitcount)),
+ v1 >>> (32 - bitcount)
+ }, wordcount);
+ }
+ }
+ return new FDBigInteger(new int[]{v0, v1}, 0);
+ }
+
+ /**
+ * Returns an <code>FDBigInteger</code> with the numerical value
+ * <code>2<sup>p2</sup></code>.
+ *
+ * @param p2 The exponent of 2.
+ * @return <code>2<sup>p2</sup></code>
+ */
+ /*@
+ @ requires p2 >= 0;
+ @ assignable \nothing;
+ @ ensures \result.value() == pow52(0, p2);
+ @*/
+ private static FDBigInteger valueOfPow2(int p2) {
+ int wordcount = p2 >> 5;
+ int bitcount = p2 & 0x1f;
+ return new FDBigInteger(new int[]{1 << bitcount}, wordcount);
+ }
+
+ /**
+ * Removes all leading zeros from this <code>FDBigInteger</code> adjusting
+ * the offset and number of non-zero leading words accordingly.
+ */
+ /*@
+ @ requires data != null;
+ @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
+ @ requires nWords == 0 ==> offset == 0;
+ @ ensures nWords == 0 ==> offset == 0;
+ @ ensures nWords > 0 ==> data[nWords - 1] != 0;
+ @*/
+ private /*@ helper @*/ void trimLeadingZeros() {
+ int i = nWords;
+ if (i > 0 && (data[--i] == 0)) {
+ //for (; i > 0 && data[i - 1] == 0; i--) ;
+ while(i > 0 && data[i - 1] == 0) {
+ i--;
+ }
+ this.nWords = i;
+ if (i == 0) { // all words are zero
+ this.offset = 0;
+ }
+ }
+ }
+
+ /**
+ * Retrieves the normalization bias of the <code>FDBigIntger</code>. The
+ * normalization bias is a left shift such that after it the highest word
+ * of the value will have the 4 highest bits equal to zero:
+ * {@code (highestWord & 0xf0000000) == 0}, but the next bit should be 1
+ * {@code (highestWord & 0x08000000) != 0}.
+ *
+ * @return The normalization bias.
+ */
+ /*@
+ @ requires this.value() > 0;
+ @*/
+ public /*@ pure @*/ int getNormalizationBias() {
+ if (nWords == 0) {
+ throw new IllegalArgumentException("Zero value cannot be normalized");
+ }
+ int zeros = Integer.numberOfLeadingZeros(data[nWords - 1]);
+ return (zeros < 4) ? 28 + zeros : zeros - 4;
+ }
+
+ // TODO: Why is anticount param needed if it is always 32 - bitcount?
+ /**
+ * Left shifts the contents of one int array into another.
+ *
+ * @param src The source array.
+ * @param idx The initial index of the source array.
+ * @param result The destination array.
+ * @param bitcount The left shift.
+ * @param anticount The left anti-shift, e.g., <code>32-bitcount</code>.
+ * @param prev The prior source value.
+ */
+ /*@
+ @ requires 0 < bitcount && bitcount < 32 && anticount == 32 - bitcount;
+ @ requires src.length >= idx && result.length > idx;
+ @ assignable result[*];
+ @ ensures AP(result, \old(idx + 1)) == \old((AP(src, idx) + UNSIGNED(prev) << (idx*32)) << bitcount);
+ @*/
+ private static void leftShift(int[] src, int idx, int result[], int bitcount, int anticount, int prev){
+ for (; idx > 0; idx--) {
+ int v = (prev << bitcount);
+ prev = src[idx - 1];
+ v |= (prev >>> anticount);
+ result[idx] = v;
+ }
+ int v = prev << bitcount;
+ result[0] = v;
+ }
+
+ /**
+ * Shifts this <code>FDBigInteger</code> to the left. The shift is performed
+ * in-place unless the <code>FDBigInteger</code> is immutable in which case
+ * a new instance of <code>FDBigInteger</code> is returned.
+ *
+ * @param shift The number of bits to shift left.
+ * @return The shifted <code>FDBigInteger</code>.
+ */
+ /*@
+ @ requires this.value() == 0 || shift == 0;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && shift > 0 && this.isImmutable;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() << shift);
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && shift > 0 && this.isImmutable;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @ ensures \result.value() == \old(this.value() << shift);
+ @*/
+ public FDBigInteger leftShift(int shift) {
+ if (shift == 0 || nWords == 0) {
+ return this;
+ }
+ int wordcount = shift >> 5;
+ int bitcount = shift & 0x1f;
+ if (this.isImmutable) {
+ if (bitcount == 0) {
+ return new FDBigInteger(Arrays.copyOf(data, nWords), offset + wordcount);
+ } else {
+ int anticount = 32 - bitcount;
+ int idx = nWords - 1;
+ int prev = data[idx];
+ int hi = prev >>> anticount;
+ int[] result;
+ if (hi != 0) {
+ result = new int[nWords + 1];
+ result[nWords] = hi;
+ } else {
+ result = new int[nWords];
+ }
+ leftShift(data,idx,result,bitcount,anticount,prev);
+ return new FDBigInteger(result, offset + wordcount);
+ }
+ } else {
+ if (bitcount != 0) {
+ int anticount = 32 - bitcount;
+ if ((data[0] << bitcount) == 0) {
+ int idx = 0;
+ int prev = data[idx];
+ for (; idx < nWords - 1; idx++) {
+ int v = (prev >>> anticount);
+ prev = data[idx + 1];
+ v |= (prev << bitcount);
+ data[idx] = v;
+ }
+ int v = prev >>> anticount;
+ data[idx] = v;
+ if(v==0) {
+ nWords--;
+ }
+ offset++;
+ } else {
+ int idx = nWords - 1;
+ int prev = data[idx];
+ int hi = prev >>> anticount;
+ int[] result = data;
+ int[] src = data;
+ if (hi != 0) {
+ if(nWords == data.length) {
+ data = result = new int[nWords + 1];
+ }
+ result[nWords++] = hi;
+ }
+ leftShift(src,idx,result,bitcount,anticount,prev);
+ }
+ }
+ offset += wordcount;
+ return this;
+ }
+ }
+
+ /**
+ * Returns the number of <code>int</code>s this <code>FDBigInteger</code> represents.
+ *
+ * @return Number of <code>int</code>s required to represent this <code>FDBigInteger</code>.
+ */
+ /*@
+ @ requires this.value() == 0;
+ @ ensures \result == 0;
+ @
+ @ also
+ @
+ @ requires this.value() > 0;
+ @ ensures ((\bigint)1) << (\result - 1) <= this.value() && this.value() <= ((\bigint)1) << \result;
+ @*/
+ private /*@ pure @*/ int size() {
+ return nWords + offset;
+ }
+
+
+ /**
+ * Computes
+ * <pre>
+ * q = (int)( this / S )
+ * this = 10 * ( this mod S )
+ * Return q.
+ * </pre>
+ * This is the iteration step of digit development for output.
+ * We assume that S has been normalized, as above, and that
+ * "this" has been left-shifted accordingly.
+ * Also assumed, of course, is that the result, q, can be expressed
+ * as an integer, {@code 0 <= q < 10}.
+ *
+ * @param S The divisor of this <code>FDBigInteger</code>.
+ * @return <code>q = (int)(this / S)</code>.
+ */
+ /*@
+ @ requires !this.isImmutable;
+ @ requires this.size() <= S.size();
+ @ requires this.data.length + this.offset >= S.size();
+ @ requires S.value() >= ((\bigint)1) << (S.size()*32 - 4);
+ @ assignable this.nWords, this.offset, this.data, this.data[*];
+ @ ensures \result == \old(this.value() / S.value());
+ @ ensures this.value() == \old(10 * (this.value() % S.value()));
+ @*/
+ public int quoRemIteration(FDBigInteger S) throws IllegalArgumentException {
+ assert !this.isImmutable : "cannot modify immutable value";
+ // ensure that this and S have the same number of
+ // digits. If S is properly normalized and q < 10 then
+ // this must be so.
+ int thSize = this.size();
+ int sSize = S.size();
+ if (thSize < sSize) {
+ // this value is significantly less than S, result of division is zero.
+ // just mult this by 10.
+ int p = multAndCarryBy10(this.data, this.nWords, this.data);
+ if(p!=0) {
+ this.data[nWords++] = p;
+ } else {
+ trimLeadingZeros();
+ }
+ return 0;
+ } else if (thSize > sSize) {
+ throw new IllegalArgumentException("disparate values");
+ }
+ // estimate q the obvious way. We will usually be
+ // right. If not, then we're only off by a little and
+ // will re-add.
+ long q = (this.data[this.nWords - 1] & LONG_MASK) / (S.data[S.nWords - 1] & LONG_MASK);
+ long diff = multDiffMe(q, S);
+ if (diff != 0L) {
+ //@ assert q != 0;
+ //@ assert this.offset == \old(Math.min(this.offset, S.offset));
+ //@ assert this.offset <= S.offset;
+
+ // q is too big.
+ // add S back in until this turns +. This should
+ // not be very many times!
+ long sum = 0L;
+ int tStart = S.offset - this.offset;
+ //@ assert tStart >= 0;
+ int[] sd = S.data;
+ int[] td = this.data;
+ while (sum == 0L) {
+ for (int sIndex = 0, tIndex = tStart; tIndex < this.nWords; sIndex++, tIndex++) {
+ sum += (td[tIndex] & LONG_MASK) + (sd[sIndex] & LONG_MASK);
+ td[tIndex] = (int) sum;
+ sum >>>= 32; // Signed or unsigned, answer is 0 or 1
+ }
+ //
+ // Originally the following line read
+ // "if ( sum !=0 && sum != -1 )"
+ // but that would be wrong, because of the
+ // treatment of the two values as entirely unsigned,
+ // it would be impossible for a carry-out to be interpreted
+ // as -1 -- it would have to be a single-bit carry-out, or +1.
+ //
+ assert sum == 0 || sum == 1 : sum; // carry out of division correction
+ q -= 1;
+ }
+ }
+ // finally, we can multiply this by 10.
+ // it cannot overflow, right, as the high-order word has
+ // at least 4 high-order zeros!
+ int p = multAndCarryBy10(this.data, this.nWords, this.data);
+ assert p == 0 : p; // Carry out of *10
+ trimLeadingZeros();
+ return (int) q;
+ }
+
+ /**
+ * Multiplies this <code>FDBigInteger</code> by 10. The operation will be
+ * performed in place unless the <code>FDBigInteger</code> is immutable in
+ * which case a new <code>FDBigInteger</code> will be returned.
+ *
+ * @return The <code>FDBigInteger</code> multiplied by 10.
+ */
+ /*@
+ @ requires this.value() == 0;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && this.isImmutable;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() * 10);
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && !this.isImmutable;
+ @ assignable this.nWords, this.data, this.data[*];
+ @ ensures \result == this;
+ @ ensures \result.value() == \old(this.value() * 10);
+ @*/
+ public FDBigInteger multBy10() {
+ if (nWords == 0) {
+ return this;
+ }
+ if (isImmutable) {
+ int[] res = new int[nWords + 1];
+ res[nWords] = multAndCarryBy10(data, nWords, res);
+ return new FDBigInteger(res, offset);
+ } else {
+ int p = multAndCarryBy10(this.data, this.nWords, this.data);
+ if (p != 0) {
+ if (nWords == data.length) {
+ if (data[0] == 0) {
+ System.arraycopy(data, 1, data, 0, --nWords);
+ offset++;
+ } else {
+ data = Arrays.copyOf(data, data.length + 1);
+ }
+ }
+ data[nWords++] = p;
+ } else {
+ trimLeadingZeros();
+ }
+ return this;
+ }
+ }
+
+ /**
+ * Multiplies this <code>FDBigInteger</code> by
+ * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>. The operation will be
+ * performed in place if possible, otherwise a new <code>FDBigInteger</code>
+ * will be returned.
+ *
+ * @param p5 The exponent of the power-of-five factor.
+ * @param p2 The exponent of the power-of-two factor.
+ * @return The multiplication result.
+ */
+ /*@
+ @ requires this.value() == 0 || p5 == 0 && p2 == 0;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && (p5 > 0 && p2 >= 0 || p5 == 0 && p2 > 0 && this.isImmutable);
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && p5 == 0 && p2 > 0 && !this.isImmutable;
+ @ assignable this.nWords, this.data, this.data[*];
+ @ ensures \result == this;
+ @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
+ @*/
+ public FDBigInteger multByPow52(int p5, int p2) {
+ if (this.nWords == 0) {
+ return this;
+ }
+ FDBigInteger res = this;
+ if (p5 != 0) {
+ int[] r;
+ int extraSize = (p2 != 0) ? 1 : 0;
+ if (p5 < SMALL_5_POW.length) {
+ r = new int[this.nWords + 1 + extraSize];
+ mult(this.data, this.nWords, SMALL_5_POW[p5], r);
+ res = new FDBigInteger(r, this.offset);
+ } else {
+ FDBigInteger pow5 = big5pow(p5);
+ r = new int[this.nWords + pow5.size() + extraSize];
+ mult(this.data, this.nWords, pow5.data, pow5.nWords, r);
+ res = new FDBigInteger(r, this.offset + pow5.offset);
+ }
+ }
+ return res.leftShift(p2);
+ }
+
+ /**
+ * Multiplies two big integers represented as int arrays.
+ *
+ * @param s1 The first array factor.
+ * @param s1Len The number of elements of <code>s1</code> to use.
+ * @param s2 The second array factor.
+ * @param s2Len The number of elements of <code>s2</code> to use.
+ * @param dst The product array.
+ */
+ /*@
+ @ requires s1 != dst && s2 != dst;
+ @ requires s1.length >= s1Len && s2.length >= s2Len && dst.length >= s1Len + s2Len;
+ @ assignable dst[0 .. s1Len + s2Len - 1];
+ @ ensures AP(dst, s1Len + s2Len) == \old(AP(s1, s1Len) * AP(s2, s2Len));
+ @*/
+ private static void mult(int[] s1, int s1Len, int[] s2, int s2Len, int[] dst) {
+ for (int i = 0; i < s1Len; i++) {
+ long v = s1[i] & LONG_MASK;
+ long p = 0L;
+ for (int j = 0; j < s2Len; j++) {
+ p += (dst[i + j] & LONG_MASK) + v * (s2[j] & LONG_MASK);
+ dst[i + j] = (int) p;
+ p >>>= 32;
+ }
+ dst[i + s2Len] = (int) p;
+ }
+ }
+
+ /**
+ * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
+ * <code>FDBigInteger</code>. Assert that the result is positive.
+ * If the subtrahend is immutable, store the result in this(minuend).
+ * If this(minuend) is immutable a new <code>FDBigInteger</code> is created.
+ *
+ * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
+ * @return This <code>FDBigInteger</code> less the subtrahend.
+ */
+ /*@
+ @ requires this.isImmutable;
+ @ requires this.value() >= subtrahend.value();
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() - subtrahend.value());
+ @
+ @ also
+ @
+ @ requires !subtrahend.isImmutable;
+ @ requires this.value() >= subtrahend.value();
+ @ assignable this.nWords, this.offset, this.data, this.data[*];
+ @ ensures \result == this;
+ @ ensures \result.value() == \old(this.value() - subtrahend.value());
+ @*/
+ public FDBigInteger leftInplaceSub(FDBigInteger subtrahend) {
+ assert this.size() >= subtrahend.size() : "result should be positive";
+ FDBigInteger minuend;
+ if (this.isImmutable) {
+ minuend = new FDBigInteger(this.data.clone(), this.offset);
+ } else {
+ minuend = this;
+ }
+ int offsetDiff = subtrahend.offset - minuend.offset;
+ int[] sData = subtrahend.data;
+ int[] mData = minuend.data;
+ int subLen = subtrahend.nWords;
+ int minLen = minuend.nWords;
+ if (offsetDiff < 0) {
+ // need to expand minuend
+ int rLen = minLen - offsetDiff;
+ if (rLen < mData.length) {
+ System.arraycopy(mData, 0, mData, -offsetDiff, minLen);
+ Arrays.fill(mData, 0, -offsetDiff, 0);
+ } else {
+ int[] r = new int[rLen];
+ System.arraycopy(mData, 0, r, -offsetDiff, minLen);
+ minuend.data = mData = r;
+ }
+ minuend.offset = subtrahend.offset;
+ minuend.nWords = minLen = rLen;
+ offsetDiff = 0;
+ }
+ long borrow = 0L;
+ int mIndex = offsetDiff;
+ for (int sIndex = 0; sIndex < subLen && mIndex < minLen; sIndex++, mIndex++) {
+ long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
+ mData[mIndex] = (int) diff;
+ borrow = diff >> 32; // signed shift
+ }
+ for (; borrow != 0 && mIndex < minLen; mIndex++) {
+ long diff = (mData[mIndex] & LONG_MASK) + borrow;
+ mData[mIndex] = (int) diff;
+ borrow = diff >> 32; // signed shift
+ }
+ assert borrow == 0L : borrow; // borrow out of subtract,
+ // result should be positive
+ minuend.trimLeadingZeros();
+ return minuend;
+ }
+
+ /**
+ * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
+ * <code>FDBigInteger</code>. Assert that the result is positive.
+ * If the this(minuend) is immutable, store the result in subtrahend.
+ * If subtrahend is immutable a new <code>FDBigInteger</code> is created.
+ *
+ * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
+ * @return This <code>FDBigInteger</code> less the subtrahend.
+ */
+ /*@
+ @ requires subtrahend.isImmutable;
+ @ requires this.value() >= subtrahend.value();
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() - subtrahend.value());
+ @
+ @ also
+ @
+ @ requires !subtrahend.isImmutable;
+ @ requires this.value() >= subtrahend.value();
+ @ assignable subtrahend.nWords, subtrahend.offset, subtrahend.data, subtrahend.data[*];
+ @ ensures \result == subtrahend;
+ @ ensures \result.value() == \old(this.value() - subtrahend.value());
+ @*/
+ public FDBigInteger rightInplaceSub(FDBigInteger subtrahend) {
+ assert this.size() >= subtrahend.size() : "result should be positive";
+ FDBigInteger minuend = this;
+ if (subtrahend.isImmutable) {
+ subtrahend = new FDBigInteger(subtrahend.data.clone(), subtrahend.offset);
+ }
+ int offsetDiff = minuend.offset - subtrahend.offset;
+ int[] sData = subtrahend.data;
+ int[] mData = minuend.data;
+ int subLen = subtrahend.nWords;
+ int minLen = minuend.nWords;
+ if (offsetDiff < 0) {
+ int rLen = minLen;
+ if (rLen < sData.length) {
+ System.arraycopy(sData, 0, sData, -offsetDiff, subLen);
+ Arrays.fill(sData, 0, -offsetDiff, 0);
+ } else {
+ int[] r = new int[rLen];
+ System.arraycopy(sData, 0, r, -offsetDiff, subLen);
+ subtrahend.data = sData = r;
+ }
+ subtrahend.offset = minuend.offset;
+ subLen -= offsetDiff;
+ offsetDiff = 0;
+ } else {
+ int rLen = minLen + offsetDiff;
+ if (rLen >= sData.length) {
+ subtrahend.data = sData = Arrays.copyOf(sData, rLen);
+ }
+ }
+ //@ assert minuend == this && minuend.value() == \old(this.value());
+ //@ assert mData == minuend.data && minLen == minuend.nWords;
+ //@ assert subtrahend.offset + subtrahend.data.length >= minuend.size();
+ //@ assert sData == subtrahend.data;
+ //@ assert AP(subtrahend.data, subtrahend.data.length) << subtrahend.offset == \old(subtrahend.value());
+ //@ assert subtrahend.offset == Math.min(\old(this.offset), minuend.offset);
+ //@ assert offsetDiff == minuend.offset - subtrahend.offset;
+ //@ assert 0 <= offsetDiff && offsetDiff + minLen <= sData.length;
+ int sIndex = 0;
+ long borrow = 0L;
+ for (; sIndex < offsetDiff; sIndex++) {
+ long diff = 0L - (sData[sIndex] & LONG_MASK) + borrow;
+ sData[sIndex] = (int) diff;
+ borrow = diff >> 32; // signed shift
+ }
+ //@ assert sIndex == offsetDiff;
+ for (int mIndex = 0; mIndex < minLen; sIndex++, mIndex++) {
+ //@ assert sIndex == offsetDiff + mIndex;
+ long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
+ sData[sIndex] = (int) diff;
+ borrow = diff >> 32; // signed shift
+ }
+ assert borrow == 0L : borrow; // borrow out of subtract,
+ // result should be positive
+ subtrahend.nWords = sIndex;
+ subtrahend.trimLeadingZeros();
+ return subtrahend;
+
+ }
+
+ /**
+ * Determines whether all elements of an array are zero for all indices less
+ * than a given index.
+ *
+ * @param a The array to be examined.
+ * @param from The index strictly below which elements are to be examined.
+ * @return Zero if all elements in range are zero, 1 otherwise.
+ */
+ /*@
+ @ requires 0 <= from && from <= a.length;
+ @ ensures \result == (AP(a, from) == 0 ? 0 : 1);
+ @*/
+ private /*@ pure @*/ static int checkZeroTail(int[] a, int from) {
+ while (from > 0) {
+ if (a[--from] != 0) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Compares the parameter with this <code>FDBigInteger</code>. Returns an
+ * integer accordingly as:
+ * <pre>{@code
+ * > 0: this > other
+ * 0: this == other
+ * < 0: this < other
+ * }</pre>
+ *
+ * @param other The <code>FDBigInteger</code> to compare.
+ * @return A negative value, zero, or a positive value according to the
+ * result of the comparison.
+ */
+ /*@
+ @ ensures \result == (this.value() < other.value() ? -1 : this.value() > other.value() ? +1 : 0);
+ @*/
+ public /*@ pure @*/ int cmp(FDBigInteger other) {
+ int aSize = nWords + offset;
+ int bSize = other.nWords + other.offset;
+ if (aSize > bSize) {
+ return 1;
+ } else if (aSize < bSize) {
+ return -1;
+ }
+ int aLen = nWords;
+ int bLen = other.nWords;
+ while (aLen > 0 && bLen > 0) {
+ int a = data[--aLen];
+ int b = other.data[--bLen];
+ if (a != b) {
+ return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
+ }
+ }
+ if (aLen > 0) {
+ return checkZeroTail(data, aLen);
+ }
+ if (bLen > 0) {
+ return -checkZeroTail(other.data, bLen);
+ }
+ return 0;
+ }
+
+ /**
+ * Compares this <code>FDBigInteger</code> with
+ * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
+ * Returns an integer accordingly as:
+ * <pre>{@code
+ * > 0: this > other
+ * 0: this == other
+ * < 0: this < other
+ * }</pre>
+ * @param p5 The exponent of the power-of-five factor.
+ * @param p2 The exponent of the power-of-two factor.
+ * @return A negative value, zero, or a positive value according to the
+ * result of the comparison.
+ */
+ /*@
+ @ requires p5 >= 0 && p2 >= 0;
+ @ ensures \result == (this.value() < pow52(p5, p2) ? -1 : this.value() > pow52(p5, p2) ? +1 : 0);
+ @*/
+ public /*@ pure @*/ int cmpPow52(int p5, int p2) {
+ if (p5 == 0) {
+ int wordcount = p2 >> 5;
+ int bitcount = p2 & 0x1f;
+ int size = this.nWords + this.offset;
+ if (size > wordcount + 1) {
+ return 1;
+ } else if (size < wordcount + 1) {
+ return -1;
+ }
+ int a = this.data[this.nWords -1];
+ int b = 1 << bitcount;
+ if (a != b) {
+ return ( (a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
+ }
+ return checkZeroTail(this.data, this.nWords - 1);
+ }
+ return this.cmp(big5pow(p5).leftShift(p2));
+ }
+
+ /**
+ * Compares this <code>FDBigInteger</code> with <code>x + y</code>. Returns a
+ * value according to the comparison as:
+ * <pre>{@code
+ * -1: this < x + y
+ * 0: this == x + y
+ * 1: this > x + y
+ * }</pre>
+ * @param x The first addend of the sum to compare.
+ * @param y The second addend of the sum to compare.
+ * @return -1, 0, or 1 according to the result of the comparison.
+ */
+ /*@
+ @ ensures \result == (this.value() < x.value() + y.value() ? -1 : this.value() > x.value() + y.value() ? +1 : 0);
+ @*/
+ public /*@ pure @*/ int addAndCmp(FDBigInteger x, FDBigInteger y) {
+ FDBigInteger big;
+ FDBigInteger small;
+ int xSize = x.size();
+ int ySize = y.size();
+ int bSize;
+ int sSize;
+ if (xSize >= ySize) {
+ big = x;
+ small = y;
+ bSize = xSize;
+ sSize = ySize;
+ } else {
+ big = y;
+ small = x;
+ bSize = ySize;
+ sSize = xSize;
+ }
+ int thSize = this.size();
+ if (bSize == 0) {
+ return thSize == 0 ? 0 : 1;
+ }
+ if (sSize == 0) {
+ return this.cmp(big);
+ }
+ if (bSize > thSize) {
+ return -1;
+ }
+ if (bSize + 1 < thSize) {
+ return 1;
+ }
+ long top = (big.data[big.nWords - 1] & LONG_MASK);
+ if (sSize == bSize) {
+ top += (small.data[small.nWords - 1] & LONG_MASK);
+ }
+ if ((top >>> 32) == 0) {
+ if (((top + 1) >>> 32) == 0) {
+ // good case - no carry extension
+ if (bSize < thSize) {
+ return 1;
+ }
+ // here sum.nWords == this.nWords
+ long v = (this.data[this.nWords - 1] & LONG_MASK);
+ if (v < top) {
+ return -1;
+ }
+ if (v > top + 1) {
+ return 1;
+ }
+ }
+ } else { // (top>>>32)!=0 guaranteed carry extension
+ if (bSize + 1 > thSize) {
+ return -1;
+ }
+ // here sum.nWords == this.nWords
+ top >>>= 32;
+ long v = (this.data[this.nWords - 1] & LONG_MASK);
+ if (v < top) {
+ return -1;
+ }
+ if (v > top + 1) {
+ return 1;
+ }
+ }
+ return this.cmp(big.add(small));
+ }
+
+ /**
+ * Makes this <code>FDBigInteger</code> immutable.
+ */
+ /*@
+ @ assignable this.isImmutable;
+ @ ensures this.isImmutable;
+ @*/
+ public void makeImmutable() {
+ this.isImmutable = true;
+ }
+
+ /**
+ * Multiplies this <code>FDBigInteger</code> by an integer.
+ *
+ * @param i The factor by which to multiply this <code>FDBigInteger</code>.
+ * @return This <code>FDBigInteger</code> multiplied by an integer.
+ */
+ /*@
+ @ requires this.value() == 0;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @
+ @ also
+ @
+ @ requires this.value() != 0;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() * UNSIGNED(i));
+ @*/
+ private FDBigInteger mult(int i) {
+ if (this.nWords == 0) {
+ return this;
+ }
+ int[] r = new int[nWords + 1];
+ mult(data, nWords, i, r);
+ return new FDBigInteger(r, offset);
+ }
+
+ /**
+ * Multiplies this <code>FDBigInteger</code> by another <code>FDBigInteger</code>.
+ *
+ * @param other The <code>FDBigInteger</code> factor by which to multiply.
+ * @return The product of this and the parameter <code>FDBigInteger</code>s.
+ */
+ /*@
+ @ requires this.value() == 0;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @
+ @ also
+ @
+ @ requires this.value() != 0 && other.value() == 0;
+ @ assignable \nothing;
+ @ ensures \result == other;
+ @
+ @ also
+ @
+ @ requires this.value() != 0 && other.value() != 0;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() * other.value());
+ @*/
+ private FDBigInteger mult(FDBigInteger other) {
+ if (this.nWords == 0) {
+ return this;
+ }
+ if (this.size() == 1) {
+ return other.mult(data[0]);
+ }
+ if (other.nWords == 0) {
+ return other;
+ }
+ if (other.size() == 1) {
+ return this.mult(other.data[0]);
+ }
+ int[] r = new int[nWords + other.nWords];
+ mult(this.data, this.nWords, other.data, other.nWords, r);
+ return new FDBigInteger(r, this.offset + other.offset);
+ }
+
+ /**
+ * Adds another <code>FDBigInteger</code> to this <code>FDBigInteger</code>.
+ *
+ * @param other The <code>FDBigInteger</code> to add.
+ * @return The sum of the <code>FDBigInteger</code>s.
+ */
+ /*@
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() + other.value());
+ @*/
+ private FDBigInteger add(FDBigInteger other) {
+ FDBigInteger big, small;
+ int bigLen, smallLen;
+ int tSize = this.size();
+ int oSize = other.size();
+ if (tSize >= oSize) {
+ big = this;
+ bigLen = tSize;
+ small = other;
+ smallLen = oSize;
+ } else {
+ big = other;
+ bigLen = oSize;
+ small = this;
+ smallLen = tSize;
+ }
+ int[] r = new int[bigLen + 1];
+ int i = 0;
+ long carry = 0L;
+ for (; i < smallLen; i++) {
+ carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) )
+ + ((i < small.offset ? 0L : (small.data[i - small.offset] & LONG_MASK)));
+ r[i] = (int) carry;
+ carry >>= 32; // signed shift.
+ }
+ for (; i < bigLen; i++) {
+ carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) );
+ r[i] = (int) carry;
+ carry >>= 32; // signed shift.
+ }
+ r[bigLen] = (int) carry;
+ return new FDBigInteger(r, 0);
+ }
+
+
+ /**
+ * Multiplies a <code>FDBigInteger</code> by an int and adds another int. The
+ * result is computed in place. This method is intended only to be invoked
+ * from
+ * <code>
+ * FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits)
+ * </code>.
+ *
+ * @param iv The factor by which to multiply this <code>FDBigInteger</code>.
+ * @param addend The value to add to the product of this
+ * <code>FDBigInteger</code> and <code>iv</code>.
+ */
+ /*@
+ @ requires this.value()*UNSIGNED(iv) + UNSIGNED(addend) < ((\bigint)1) << ((this.data.length + this.offset)*32);
+ @ assignable this.data[*];
+ @ ensures this.value() == \old(this.value()*UNSIGNED(iv) + UNSIGNED(addend));
+ @*/
+ private /*@ helper @*/ void multAddMe(int iv, int addend) {
+ long v = iv & LONG_MASK;
+ // unroll 0th iteration, doing addition.
+ long p = v * (data[0] & LONG_MASK) + (addend & LONG_MASK);
+ data[0] = (int) p;
+ p >>>= 32;
+ for (int i = 1; i < nWords; i++) {
+ p += v * (data[i] & LONG_MASK);
+ data[i] = (int) p;
+ p >>>= 32;
+ }
+ if (p != 0L) {
+ data[nWords++] = (int) p; // will fail noisily if illegal!
+ }
+ }
+
+ //
+ // original doc:
+ //
+ // do this -=q*S
+ // returns borrow
+ //
+ /**
+ * Multiplies the parameters and subtracts them from this
+ * <code>FDBigInteger</code>.
+ *
+ * @param q The integer parameter.
+ * @param S The <code>FDBigInteger</code> parameter.
+ * @return <code>this - q*S</code>.
+ */
+ /*@
+ @ ensures nWords == 0 ==> offset == 0;
+ @ ensures nWords > 0 ==> data[nWords - 1] != 0;
+ @*/
+ /*@
+ @ requires 0 < q && q <= (1L << 31);
+ @ requires data != null;
+ @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
+ @ requires !this.isImmutable;
+ @ requires this.size() == S.size();
+ @ requires this != S;
+ @ assignable this.nWords, this.offset, this.data, this.data[*];
+ @ ensures -q <= \result && \result <= 0;
+ @ ensures this.size() == \old(this.size());
+ @ ensures this.value() + (\result << (this.size()*32)) == \old(this.value() - q*S.value());
+ @ ensures this.offset == \old(Math.min(this.offset, S.offset));
+ @ ensures \old(this.offset <= S.offset) ==> this.nWords == \old(this.nWords);
+ @ ensures \old(this.offset <= S.offset) ==> this.offset == \old(this.offset);
+ @ ensures \old(this.offset <= S.offset) ==> this.data == \old(this.data);
+ @
+ @ also
+ @
+ @ requires q == 0;
+ @ assignable \nothing;
+ @ ensures \result == 0;
+ @*/
+ private /*@ helper @*/ long multDiffMe(long q, FDBigInteger S) {
+ long diff = 0L;
+ if (q != 0) {
+ int deltaSize = S.offset - this.offset;
+ if (deltaSize >= 0) {
+ int[] sd = S.data;
+ int[] td = this.data;
+ for (int sIndex = 0, tIndex = deltaSize; sIndex < S.nWords; sIndex++, tIndex++) {
+ diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
+ td[tIndex] = (int) diff;
+ diff >>= 32; // N.B. SIGNED shift.
+ }
+ } else {
+ deltaSize = -deltaSize;
+ int[] rd = new int[nWords + deltaSize];
+ int sIndex = 0;
+ int rIndex = 0;
+ int[] sd = S.data;
+ for (; rIndex < deltaSize && sIndex < S.nWords; sIndex++, rIndex++) {
+ diff -= q * (sd[sIndex] & LONG_MASK);
+ rd[rIndex] = (int) diff;
+ diff >>= 32; // N.B. SIGNED shift.
+ }
+ int tIndex = 0;
+ int[] td = this.data;
+ for (; sIndex < S.nWords; sIndex++, tIndex++, rIndex++) {
+ diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
+ rd[rIndex] = (int) diff;
+ diff >>= 32; // N.B. SIGNED shift.
+ }
+ this.nWords += deltaSize;
+ this.offset -= deltaSize;
+ this.data = rd;
+ }
+ }
+ return diff;
+ }
+
+
+ /**
+ * Multiplies by 10 a big integer represented as an array. The final carry
+ * is returned.
+ *
+ * @param src The array representation of the big integer.
+ * @param srcLen The number of elements of <code>src</code> to use.
+ * @param dst The product array.
+ * @return The final carry of the multiplication.
+ */
+ /*@
+ @ requires src.length >= srcLen && dst.length >= srcLen;
+ @ assignable dst[0 .. srcLen - 1];
+ @ ensures 0 <= \result && \result < 10;
+ @ ensures AP(dst, srcLen) + (\result << (srcLen*32)) == \old(AP(src, srcLen) * 10);
+ @*/
+ private static int multAndCarryBy10(int[] src, int srcLen, int[] dst) {
+ long carry = 0;
+ for (int i = 0; i < srcLen; i++) {
+ long product = (src[i] & LONG_MASK) * 10L + carry;
+ dst[i] = (int) product;
+ carry = product >>> 32;
+ }
+ return (int) carry;
+ }
+
+ /**
+ * Multiplies by a constant value a big integer represented as an array.
+ * The constant factor is an <code>int</code>.
+ *
+ * @param src The array representation of the big integer.
+ * @param srcLen The number of elements of <code>src</code> to use.
+ * @param value The constant factor by which to multiply.
+ * @param dst The product array.
+ */
+ /*@
+ @ requires src.length >= srcLen && dst.length >= srcLen + 1;
+ @ assignable dst[0 .. srcLen];
+ @ ensures AP(dst, srcLen + 1) == \old(AP(src, srcLen) * UNSIGNED(value));
+ @*/
+ private static void mult(int[] src, int srcLen, int value, int[] dst) {
+ long val = value & LONG_MASK;
+ long carry = 0;
+ for (int i = 0; i < srcLen; i++) {
+ long product = (src[i] & LONG_MASK) * val + carry;
+ dst[i] = (int) product;
+ carry = product >>> 32;
+ }
+ dst[srcLen] = (int) carry;
+ }
+
+ /**
+ * Multiplies by a constant value a big integer represented as an array.
+ * The constant factor is a long represent as two <code>int</code>s.
+ *
+ * @param src The array representation of the big integer.
+ * @param srcLen The number of elements of <code>src</code> to use.
+ * @param v0 The lower 32 bits of the long factor.
+ * @param v1 The upper 32 bits of the long factor.
+ * @param dst The product array.
+ */
+ /*@
+ @ requires src != dst;
+ @ requires src.length >= srcLen && dst.length >= srcLen + 2;
+ @ assignable dst[0 .. srcLen + 1];
+ @ ensures AP(dst, srcLen + 2) == \old(AP(src, srcLen) * (UNSIGNED(v0) + (UNSIGNED(v1) << 32)));
+ @*/
+ private static void mult(int[] src, int srcLen, int v0, int v1, int[] dst) {
+ long v = v0 & LONG_MASK;
+ long carry = 0;
+ for (int j = 0; j < srcLen; j++) {
+ long product = v * (src[j] & LONG_MASK) + carry;
+ dst[j] = (int) product;
+ carry = product >>> 32;
+ }
+ dst[srcLen] = (int) carry;
+ v = v1 & LONG_MASK;
+ carry = 0;
+ for (int j = 0; j < srcLen; j++) {
+ long product = (dst[j + 1] & LONG_MASK) + v * (src[j] & LONG_MASK) + carry;
+ dst[j + 1] = (int) product;
+ carry = product >>> 32;
+ }
+ dst[srcLen + 1] = (int) carry;
+ }
+
+ // Fails assertion for negative exponent.
+ /**
+ * Computes <code>5</code> raised to a given power.
+ *
+ * @param p The exponent of 5.
+ * @return <code>5<sup>p</sup></code>.
+ */
+ private static FDBigInteger big5pow(int p) {
+ assert p >= 0 : p; // negative power of 5
+ if (p < MAX_FIVE_POW) {
+ return POW_5_CACHE[p];
+ }
+ return big5powRec(p);
+ }
+
+ // slow path
+ /**
+ * Computes <code>5</code> raised to a given power.
+ *
+ * @param p The exponent of 5.
+ * @return <code>5<sup>p</sup></code>.
+ */
+ private static FDBigInteger big5powRec(int p) {
+ if (p < MAX_FIVE_POW) {
+ return POW_5_CACHE[p];
+ }
+ // construct the value.
+ // recursively.
+ int q, r;
+ // in order to compute 5^p,
+ // compute its square root, 5^(p/2) and square.
+ // or, let q = p / 2, r = p -q, then
+ // 5^p = 5^(q+r) = 5^q * 5^r
+ q = p >> 1;
+ r = p - q;
+ FDBigInteger bigq = big5powRec(q);
+ if (r < SMALL_5_POW.length) {
+ return bigq.mult(SMALL_5_POW[r]);
+ } else {
+ return bigq.mult(big5powRec(r));
+ }
+ }
+
+ // for debugging ...
+ /**
+ * Converts this <code>FDBigInteger</code> to a hexadecimal string.
+ *
+ * @return The hexadecimal string representation.
+ */
+ public String toHexString(){
+ if(nWords ==0) {
+ return "0";
+ }
+ StringBuilder sb = new StringBuilder((nWords +offset)*8);
+ for(int i= nWords -1; i>=0; i--) {
+ String subStr = Integer.toHexString(data[i]);
+ for(int j = subStr.length(); j<8; j++) {
+ sb.append('0');
+ }
+ sb.append(subStr);
+ }
+ for(int i=offset; i>0; i--) {
+ sb.append("00000000");
+ }
+ return sb.toString();
+ }
+
+ // for debugging ...
+ /**
+ * Converts this <code>FDBigInteger</code> to a <code>BigInteger</code>.
+ *
+ * @return The <code>BigInteger</code> representation.
+ */
+ public BigInteger toBigInteger() {
+ byte[] magnitude = new byte[nWords * 4 + 1];
+ for (int i = 0; i < nWords; i++) {
+ int w = data[i];
+ magnitude[magnitude.length - 4 * i - 1] = (byte) w;
+ magnitude[magnitude.length - 4 * i - 2] = (byte) (w >> 8);
+ magnitude[magnitude.length - 4 * i - 3] = (byte) (w >> 16);
+ magnitude[magnitude.length - 4 * i - 4] = (byte) (w >> 24);
+ }
+ return new BigInteger(magnitude).shiftLeft(offset * 32);
+ }
+
+ // for debugging ...
+ /**
+ * Converts this <code>FDBigInteger</code> to a string.
+ *
+ * @return The string representation.
+ */
+ @Override
+ public String toString(){
+ return toBigInteger().toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/math/FloatConsts.java Tue Dec 22 12:17:25 2015 +0000
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.math;
+
+/**
+ * This class contains additional constants documenting limits of the
+ * <code>float</code> type.
+ *
+ * @author Joseph D. Darcy
+ */
+
+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.
+ */
+ 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)));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java Tue Dec 22 12:17:25 2015 +0000
@@ -0,0 +1,2552 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.math;
+
+import java.util.Arrays;
+import java.util.regex.*;
+
+/**
+ * A class for converting between ASCII and decimal representations of a single
+ * or double precision floating point number. Most conversions are provided via
+ * static convenience methods, although a <code>BinaryToASCIIConverter</code>
+ * instance may be obtained and reused.
+ */
+public class FloatingDecimal{
+ //
+ // Constants of the implementation;
+ // most are IEEE-754 related.
+ // (There are more really boring constants at the end.)
+ //
+ static final int EXP_SHIFT = DoubleConsts.SIGNIFICAND_WIDTH - 1;
+ static final long FRACT_HOB = ( 1L<<EXP_SHIFT ); // assumed High-Order bit
+ static final long EXP_ONE = ((long)DoubleConsts.EXP_BIAS)<<EXP_SHIFT; // exponent of 1.0
+ static final int MAX_SMALL_BIN_EXP = 62;
+ static final int MIN_SMALL_BIN_EXP = -( 63 / 3 );
+ static final int MAX_DECIMAL_DIGITS = 15;
+ static final int MAX_DECIMAL_EXPONENT = 308;
+ static final int MIN_DECIMAL_EXPONENT = -324;
+ static final int BIG_DECIMAL_EXPONENT = 324; // i.e. abs(MIN_DECIMAL_EXPONENT)
+ static final int MAX_NDIGITS = 1100;
+
+ static final int SINGLE_EXP_SHIFT = FloatConsts.SIGNIFICAND_WIDTH - 1;
+ static final int SINGLE_FRACT_HOB = 1<<SINGLE_EXP_SHIFT;
+ static final int SINGLE_MAX_DECIMAL_DIGITS = 7;
+ static final int SINGLE_MAX_DECIMAL_EXPONENT = 38;
+ static final int SINGLE_MIN_DECIMAL_EXPONENT = -45;
+ static final int SINGLE_MAX_NDIGITS = 200;
+
+ static final int INT_DECIMAL_DIGITS = 9;
+
+ /**
+ * Converts a double precision floating point value to a <code>String</code>.
+ *
+ * @param d The double precision value.
+ * @return The value converted to a <code>String</code>.
+ */
+ public static String toJavaFormatString(double d) {
+ return getBinaryToASCIIConverter(d).toJavaFormatString();
+ }
+
+ /**
+ * Converts a single precision floating point value to a <code>String</code>.
+ *
+ * @param f The single precision value.
+ * @return The value converted to a <code>String</code>.
+ */
+ public static String toJavaFormatString(float f) {
+ return getBinaryToASCIIConverter(f).toJavaFormatString();
+ }
+
+ /**
+ * Appends a double precision floating point value to an <code>Appendable</code>.
+ * @param d The double precision value.
+ * @param buf The <code>Appendable</code> with the value appended.
+ */
+ public static void appendTo(double d, Appendable buf) {
+ getBinaryToASCIIConverter(d).appendTo(buf);
+ }
+
+ /**
+ * Appends a single precision floating point value to an <code>Appendable</code>.
+ * @param f The single precision value.
+ * @param buf The <code>Appendable</code> with the value appended.
+ */
+ public static void appendTo(float f, Appendable buf) {
+ getBinaryToASCIIConverter(f).appendTo(buf);
+ }
+
+ /**
+ * Converts a <code>String</code> to a double precision floating point value.
+ *
+ * @param s The <code>String</code> to convert.
+ * @return The double precision value.
+ * @throws NumberFormatException If the <code>String</code> does not
+ * represent a properly formatted double precision value.
+ */
+ public static double parseDouble(String s) throws NumberFormatException {
+ return readJavaFormatString(s).doubleValue();
+ }
+
+ /**
+ * Converts a <code>String</code> to a single precision floating point value.
+ *
+ * @param s The <code>String</code> to convert.
+ * @return The single precision value.
+ * @throws NumberFormatException If the <code>String</code> does not
+ * represent a properly formatted single precision value.
+ */
+ public static float parseFloat(String s) throws NumberFormatException {
+ return readJavaFormatString(s).floatValue();
+ }
+
+ /**
+ * A converter which can process single or double precision floating point
+ * values into an ASCII <code>String</code> representation.
+ */
+ public interface BinaryToASCIIConverter {
+ /**
+ * Converts a floating point value into an ASCII <code>String</code>.
+ * @return The value converted to a <code>String</code>.
+ */
+ public String toJavaFormatString();
+
+ /**
+ * Appends a floating point value to an <code>Appendable</code>.
+ * @param buf The <code>Appendable</code> to receive the value.
+ */
+ public void appendTo(Appendable buf);
+
+ /**
+ * Retrieves the decimal exponent most closely corresponding to this value.
+ * @return The decimal exponent.
+ */
+ public int getDecimalExponent();
+
+ /**
+ * Retrieves the value as an array of digits.
+ * @param digits The digit array.
+ * @return The number of valid digits copied into the array.
+ */
+ public int getDigits(char[] digits);
+
+ /**
+ * Indicates the sign of the value.
+ * @return {@code value < 0.0}.
+ */
+ public boolean isNegative();
+
+ /**
+ * Indicates whether the value is either infinite or not a number.
+ *
+ * @return <code>true</code> if and only if the value is <code>NaN</code>
+ * or infinite.
+ */
+ public boolean isExceptional();
+
+ /**
+ * Indicates whether the value was rounded up during the binary to ASCII
+ * conversion.
+ *
+ * @return <code>true</code> if and only if the value was rounded up.
+ */
+ public boolean digitsRoundedUp();
+
+ /**
+ * Indicates whether the binary to ASCII conversion was exact.
+ *
+ * @return <code>true</code> if any only if the conversion was exact.
+ */
+ public boolean decimalDigitsExact();
+ }
+
+ /**
+ * A <code>BinaryToASCIIConverter</code> which represents <code>NaN</code>
+ * and infinite values.
+ */
+ private static class ExceptionalBinaryToASCIIBuffer implements BinaryToASCIIConverter {
+ private final String image;
+ private boolean isNegative;
+
+ public ExceptionalBinaryToASCIIBuffer(String image, boolean isNegative) {
+ this.image = image;
+ this.isNegative = isNegative;
+ }
+
+ @Override
+ public String toJavaFormatString() {
+ return image;
+ }
+
+ @Override
+ public void appendTo(Appendable buf) {
+ if (buf instanceof StringBuilder) {
+ ((StringBuilder) buf).append(image);
+ } else if (buf instanceof StringBuffer) {
+ ((StringBuffer) buf).append(image);
+ } else {
+ assert false;
+ }
+ }
+
+ @Override
+ public int getDecimalExponent() {
+ throw new IllegalArgumentException("Exceptional value does not have an exponent");
+ }
+
+ @Override
+ public int getDigits(char[] digits) {
+ throw new IllegalArgumentException("Exceptional value does not have digits");
+ }
+
+ @Override
+ public boolean isNegative() {
+ return isNegative;
+ }
+
+ @Override
+ public boolean isExceptional() {
+ return true;
+ }
+
+ @Override
+ public boolean digitsRoundedUp() {
+ throw new IllegalArgumentException("Exceptional value is not rounded");
+ }
+
+ @Override
+ public boolean decimalDigitsExact() {
+ throw new IllegalArgumentException("Exceptional value is not exact");
+ }
+ }
+
+ private static final String INFINITY_REP = "Infinity";
+ private static final int INFINITY_LENGTH = INFINITY_REP.length();
+ private static final String NAN_REP = "NaN";
+ private static final int NAN_LENGTH = NAN_REP.length();
+
+ private static final BinaryToASCIIConverter B2AC_POSITIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer(INFINITY_REP, false);
+ private static final BinaryToASCIIConverter B2AC_NEGATIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer("-" + INFINITY_REP, true);
+ private static final BinaryToASCIIConverter B2AC_NOT_A_NUMBER = new ExceptionalBinaryToASCIIBuffer(NAN_REP, false);
+ private static final BinaryToASCIIConverter B2AC_POSITIVE_ZERO = new BinaryToASCIIBuffer(false, new char[]{'0'});
+ private static final BinaryToASCIIConverter B2AC_NEGATIVE_ZERO = new BinaryToASCIIBuffer(true, new char[]{'0'});
+
+ /**
+ * A buffered implementation of <code>BinaryToASCIIConverter</code>.
+ */
+ static class BinaryToASCIIBuffer implements BinaryToASCIIConverter {
+ private boolean isNegative;
+ private int decExponent;
+ private int firstDigitIndex;
+ private int nDigits;
+ private final char[] digits;
+ private final char[] buffer = new char[26];
+
+ //
+ // The fields below provide additional information about the result of
+ // the binary to decimal digits conversion done in dtoa() and roundup()
+ // methods. They are changed if needed by those two methods.
+ //
+
+ // True if the dtoa() binary to decimal conversion was exact.
+ private boolean exactDecimalConversion = false;
+
+ // True if the result of the binary to decimal conversion was rounded-up
+ // at the end of the conversion process, i.e. roundUp() method was called.
+ private boolean decimalDigitsRoundedUp = false;
+
+ /**
+ * Default constructor; used for non-zero values,
+ * <code>BinaryToASCIIBuffer</code> may be thread-local and reused
+ */
+ BinaryToASCIIBuffer(){
+ this.digits = new char[20];
+ }
+
+ /**
+ * Creates a specialized value (positive and negative zeros).
+ */
+ BinaryToASCIIBuffer(boolean isNegative, char[] digits){
+ this.isNegative = isNegative;
+ this.decExponent = 0;
+ this.digits = digits;
+ this.firstDigitIndex = 0;
+ this.nDigits = digits.length;
+ }
+
+ @Override
+ public String toJavaFormatString() {
+ int len = getChars(buffer);
+ return new String(buffer, 0, len);
+ }
+
+ @Override
+ public void appendTo(Appendable buf) {
+ int len = getChars(buffer);
+ if (buf instanceof StringBuilder) {
+ ((StringBuilder) buf).append(buffer, 0, len);
+ } else if (buf instanceof StringBuffer) {
+ ((StringBuffer) buf).append(buffer, 0, len);
+ } else {
+ assert false;
+ }
+ }
+
+ @Override
+ public int getDecimalExponent() {
+ return decExponent;
+ }
+
+ @Override
+ public int getDigits(char[] digits) {
+ System.arraycopy(this.digits,firstDigitIndex,digits,0,this.nDigits);
+ return this.nDigits;
+ }
+
+ @Override
+ public boolean isNegative() {
+ return isNegative;
+ }
+
+ @Override
+ public boolean isExceptional() {
+ return false;
+ }
+
+ @Override
+ public boolean digitsRoundedUp() {
+ return decimalDigitsRoundedUp;
+ }
+
+ @Override
+ public boolean decimalDigitsExact() {
+ return exactDecimalConversion;
+ }
+
+ private void setSign(boolean isNegative) {
+ this.isNegative = isNegative;
+ }
+
+ /**
+ * This is the easy subcase --
+ * all the significant bits, after scaling, are held in lvalue.
+ * negSign and decExponent tell us what processing and scaling
+ * has already been done. Exceptional cases have already been
+ * stripped out.
+ * 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, int insignificantDigits ){
+ if ( insignificantDigits != 0 ){
+ // Discard non-significant low-order bits, while rounding,
+ // up to insignificant value.
+ long pow10 = FDBigInteger.LONG_5_POW[insignificantDigits] << insignificantDigits; // 10^i == 5^i * 2^i;
+ long residue = lvalue % pow10;
+ lvalue /= pow10;
+ decExponent += insignificantDigits;
+ if ( residue >= (pow10>>1) ){
+ // round up based on the low-order bits we're discarding
+ lvalue++;
+ }
+ }
+ int digitno = digits.length -1;
+ int c;
+ if ( lvalue <= Integer.MAX_VALUE ){
+ assert lvalue > 0L : lvalue; // lvalue <= 0
+ // even easier subcase!
+ // can do int arithmetic rather than long!
+ int ivalue = (int)lvalue;
+ c = ivalue%10;
+ ivalue /= 10;
+ while ( c == 0 ){
+ decExponent++;
+ c = ivalue%10;
+ ivalue /= 10;
+ }
+ while ( ivalue != 0){
+ digits[digitno--] = (char)(c+'0');
+ decExponent++;
+ c = ivalue%10;
+ ivalue /= 10;
+ }
+ digits[digitno] = (char)(c+'0');
+ } else {
+ // same algorithm as above (same bugs, too )
+ // but using long arithmetic.
+ c = (int)(lvalue%10L);
+ lvalue /= 10L;
+ while ( c == 0 ){
+ decExponent++;
+ c = (int)(lvalue%10L);
+ lvalue /= 10L;
+ }
+ while ( lvalue != 0L ){
+ digits[digitno--] = (char)(c+'0');
+ decExponent++;
+ c = (int)(lvalue%10L);
+ lvalue /= 10;
+ }
+ digits[digitno] = (char)(c+'0');
+ }
+ this.decExponent = decExponent+1;
+ this.firstDigitIndex = digitno;
+ this.nDigits = this.digits.length - digitno;
+ }
+
+ private void dtoa( int binExp, long fractBits, int nSignificantBits, boolean isCompatibleFormat)
+ {
+ assert fractBits > 0 ; // fractBits here can't be zero or negative
+ assert (fractBits & FRACT_HOB)!=0 ; // Hi-order bit should be set
+ // Examine number. Determine if it is an easy case,
+ // which we can do pretty trivially using float/long conversion,
+ // or whether we must do real work.
+ final int tailZeros = Long.numberOfTrailingZeros(fractBits);
+
+ // number of significant bits of fractBits;
+ final int nFractBits = EXP_SHIFT+1-tailZeros;
+
+ // reset flags to default values as dtoa() does not always set these
+ // flags and a prior call to dtoa() might have set them to incorrect
+ // values with respect to the current state.
+ decimalDigitsRoundedUp = false;
+ exactDecimalConversion = false;
+
+ // number of significant bits to the right of the point.
+ int nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
+ if ( binExp <= MAX_SMALL_BIN_EXP && binExp >= MIN_SMALL_BIN_EXP ){
+ // Look more closely at the number to decide if,
+ // with scaling by 10^nTinyBits, the result will fit in
+ // a long.
+ if ( (nTinyBits < FDBigInteger.LONG_5_POW.length) && ((nFractBits + N_5_BITS[nTinyBits]) < 64 ) ){
+ //
+ // We can do this:
+ // take the fraction bits, which are normalized.
+ // (a) nTinyBits == 0: Shift left or right appropriately
+ // to align the binary point at the extreme right, i.e.
+ // where a long int point is expected to be. The integer
+ // result is easily converted to a string.
+ // (b) nTinyBits > 0: Shift right by EXP_SHIFT-nFractBits,
+ // which effectively converts to long and scales by
+ // 2^nTinyBits. Then multiply by 5^nTinyBits to
+ // complete the scaling. We know this won't overflow
+ // because we just counted the number of bits necessary
+ // in the result. The integer you get from this can
+ // then be converted to a string pretty easily.
+ //
+ if ( nTinyBits == 0 ) {
+ int insignificant;
+ if ( binExp > nSignificantBits ){
+ insignificant = insignificantDigitsForPow2(binExp-nSignificantBits-1);
+ } else {
+ insignificant = 0;
+ }
+ if ( binExp >= EXP_SHIFT ){
+ fractBits <<= (binExp-EXP_SHIFT);
+ } else {
+ fractBits >>>= (EXP_SHIFT-binExp) ;
+ }
+ developLongDigits( 0, fractBits, insignificant );
+ return;
+ }
+ //
+ // The following causes excess digits to be printed
+ // out in the single-float case. Our manipulation of
+ // halfULP here is apparently not correct. If we
+ // better understand how this works, perhaps we can
+ // use this special case again. But for the time being,
+ // we do not.
+ // else {
+ // fractBits >>>= EXP_SHIFT+1-nFractBits;
+ // fractBits//= long5pow[ nTinyBits ];
+ // halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
+ // developLongDigits( -nTinyBits, fractBits, insignificantDigits(halfULP) );
+ // return;
+ // }
+ //
+ }
+ }
+ //
+ // This is the hard case. We are going to compute large positive
+ // integers B and S and integer decExp, s.t.
+ // d = ( B / S )// 10^decExp
+ // 1 <= B / S < 10
+ // Obvious choices are:
+ // decExp = floor( log10(d) )
+ // B = d// 2^nTinyBits// 10^max( 0, -decExp )
+ // S = 10^max( 0, decExp)// 2^nTinyBits
+ // (noting that nTinyBits has already been forced to non-negative)
+ // I am also going to compute a large positive integer
+ // M = (1/2^nSignificantBits)// 2^nTinyBits// 10^max( 0, -decExp )
+ // i.e. M is (1/2) of the ULP of d, scaled like B.
+ // When we iterate through dividing B/S and picking off the
+ // quotient bits, we will know when to stop when the remainder
+ // is <= M.
+ //
+ // We keep track of powers of 2 and powers of 5.
+ //
+ int decExp = estimateDecExp(fractBits,binExp);
+ int B2, B5; // powers of 2 and powers of 5, respectively, in B
+ int S2, S5; // powers of 2 and powers of 5, respectively, in S
+ int M2, M5; // powers of 2 and powers of 5, respectively, in M
+
+ B5 = Math.max( 0, -decExp );
+ B2 = B5 + nTinyBits + binExp;
+
+ S5 = Math.max( 0, decExp );
+ S2 = S5 + nTinyBits;
+
+ M5 = B5;
+ M2 = B2 - nSignificantBits;
+
+ //
+ // the long integer fractBits contains the (nFractBits) interesting
+ // bits from the mantissa of d ( hidden 1 added if necessary) followed
+ // by (EXP_SHIFT+1-nFractBits) zeros. In the interest of compactness,
+ // I will shift out those zeros before turning fractBits into a
+ // FDBigInteger. The resulting whole number will be
+ // d * 2^(nFractBits-1-binExp).
+ //
+ fractBits >>>= tailZeros;
+ B2 -= nFractBits-1;
+ int common2factor = Math.min( B2, S2 );
+ B2 -= common2factor;
+ S2 -= common2factor;
+ M2 -= common2factor;
+
+ //
+ // HACK!! For exact powers of two, the next smallest number
+ // is only half as far away as we think (because the meaning of
+ // ULP changes at power-of-two bounds) for this reason, we
+ // hack M2. Hope this works.
+ //
+ if ( nFractBits == 1 ) {
+ M2 -= 1;
+ }
+
+ if ( M2 < 0 ){
+ // oops.
+ // since we cannot scale M down far enough,
+ // we must scale the other values up.
+ B2 -= M2;
+ S2 -= M2;
+ M2 = 0;
+ }
+ //
+ // Construct, Scale, iterate.
+ // Some day, we'll write a stopping test that takes
+ // account of the asymmetry of the spacing of floating-point
+ // numbers below perfect powers of 2
+ // 26 Sept 96 is not that day.
+ // So we use a symmetric test.
+ //
+ int ndigit = 0;
+ boolean low, high;
+ long lowDigitDifference;
+ int q;
+
+ //
+ // Detect the special cases where all the numbers we are about
+ // to compute will fit in int or long integers.
+ // In these cases, we will avoid doing FDBigInteger arithmetic.
+ // We use the same algorithms, except that we "normalize"
+ // our FDBigIntegers before iterating. This is to make division easier,
+ // as it makes our fist guess (quotient of high-order words)
+ // more accurate!
+ //
+ // Some day, we'll write a stopping test that takes
+ // account of the asymmetry of the spacing of floating-point
+ // numbers below perfect powers of 2
+ // 26 Sept 96 is not that day.
+ // So we use a symmetric test.
+ //
+ // binary digits needed to represent B, approx.
+ int Bbits = nFractBits + B2 + (( B5 < N_5_BITS.length )? N_5_BITS[B5] : ( B5*3 ));
+
+ // binary digits needed to represent 10*S, approx.
+ int tenSbits = S2+1 + (( (S5+1) < N_5_BITS.length )? N_5_BITS[(S5+1)] : ( (S5+1)*3 ));
+ if ( Bbits < 64 && tenSbits < 64){
+ if ( Bbits < 32 && tenSbits < 32){
+ // wa-hoo! They're all ints!
+ int b = ((int)fractBits * FDBigInteger.SMALL_5_POW[B5] ) << B2;
+ int s = FDBigInteger.SMALL_5_POW[S5] << S2;
+ int m = FDBigInteger.SMALL_5_POW[M5] << M2;
+ int tens = s * 10;
+ //
+ // Unroll the first iteration. If our decExp estimate
+ // was too high, our first quotient will be zero. In this
+ // case, we discard it and decrement decExp.
+ //
+ ndigit = 0;
+ q = b / s;
+ b = 10 * ( b % s );
+ m *= 10;
+ low = (b < m );
+ high = (b+m > tens );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ //
+ // HACK! Java spec sez that we always have at least
+ // one digit after the . in either F- or E-form output.
+ // Thus we will need more than one digit if we're using
+ // E-form
+ //
+ if ( !isCompatibleFormat ||decExp < -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = b / s;
+ b = 10 * ( b % s );
+ m *= 10;
+ assert q < 10 : q; // excessively large digit
+ if ( m > 0L ){
+ low = (b < m );
+ high = (b+m > tens );
+ } else {
+ // hack -- m might overflow!
+ // in this case, it is certainly > b,
+ // which won't
+ // and b+m > tens, too, since that has overflowed
+ // either!
+ low = true;
+ high = true;
+ }
+ digits[ndigit++] = (char)('0' + q);
+ }
+ lowDigitDifference = (b<<1) - tens;
+ exactDecimalConversion = (b == 0);
+ } else {
+ // still good! they're all longs!
+ long b = (fractBits * FDBigInteger.LONG_5_POW[B5] ) << B2;
+ long s = FDBigInteger.LONG_5_POW[S5] << S2;
+ long m = FDBigInteger.LONG_5_POW[M5] << M2;
+ long tens = s * 10L;
+ //
+ // Unroll the first iteration. If our decExp estimate
+ // was too high, our first quotient will be zero. In this
+ // case, we discard it and decrement decExp.
+ //
+ ndigit = 0;
+ q = (int) ( b / s );
+ b = 10L * ( b % s );
+ m *= 10L;
+ low = (b < m );
+ high = (b+m > tens );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ //
+ // HACK! Java spec sez that we always have at least
+ // one digit after the . in either F- or E-form output.
+ // Thus we will need more than one digit if we're using
+ // E-form
+ //
+ if ( !isCompatibleFormat || decExp < -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = (int) ( b / s );
+ b = 10 * ( b % s );
+ m *= 10;
+ assert q < 10 : q; // excessively large digit
+ if ( m > 0L ){
+ low = (b < m );
+ high = (b+m > tens );
+ } else {
+ // hack -- m might overflow!
+ // in this case, it is certainly > b,
+ // which won't
+ // and b+m > tens, too, since that has overflowed
+ // either!
+ low = true;
+ high = true;
+ }
+ digits[ndigit++] = (char)('0' + q);
+ }
+ lowDigitDifference = (b<<1) - tens;
+ exactDecimalConversion = (b == 0);
+ }
+ } else {
+ //
+ // We really must do FDBigInteger arithmetic.
+ // Fist, construct our FDBigInteger initial values.
+ //
+ FDBigInteger Sval = FDBigInteger.valueOfPow52(S5, S2);
+ int shiftBias = Sval.getNormalizationBias();
+ Sval = Sval.leftShift(shiftBias); // normalize so that division works better
+
+ FDBigInteger Bval = FDBigInteger.valueOfMulPow52(fractBits, B5, B2 + shiftBias);
+ FDBigInteger Mval = FDBigInteger.valueOfPow52(M5 + 1, M2 + shiftBias + 1);
+
+ FDBigInteger tenSval = FDBigInteger.valueOfPow52(S5 + 1, S2 + shiftBias + 1); //Sval.mult( 10 );
+ //
+ // Unroll the first iteration. If our decExp estimate
+ // was too high, our first quotient will be zero. In this
+ // case, we discard it and decrement decExp.
+ //
+ ndigit = 0;
+ q = Bval.quoRemIteration( Sval );
+ low = (Bval.cmp( Mval ) < 0);
+ high = tenSval.addAndCmp(Bval,Mval)<=0;
+
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ //
+ // HACK! Java spec sez that we always have at least
+ // one digit after the . in either F- or E-form output.
+ // Thus we will need more than one digit if we're using
+ // E-form
+ //
+ if (!isCompatibleFormat || decExp < -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = Bval.quoRemIteration( Sval );
+ assert q < 10 : q; // excessively large digit
+ Mval = Mval.multBy10(); //Mval = Mval.mult( 10 );
+ low = (Bval.cmp( Mval ) < 0);
+ high = tenSval.addAndCmp(Bval,Mval)<=0;
+ digits[ndigit++] = (char)('0' + q);
+ }
+ if ( high && low ){
+ Bval = Bval.leftShift(1);
+ lowDigitDifference = Bval.cmp(tenSval);
+ } else {
+ lowDigitDifference = 0L; // this here only for flow analysis!
+ }
+ exactDecimalConversion = (Bval.cmp( FDBigInteger.ZERO ) == 0);
+ }
+ this.decExponent = decExp+1;
+ this.firstDigitIndex = 0;
+ this.nDigits = ndigit;
+ //
+ // Last digit gets rounded based on stopping condition.
+ //
+ if ( high ){
+ if ( low ){
+ if ( lowDigitDifference == 0L ){
+ // it's a tie!
+ // choose based on which digits we like.
+ if ( (digits[firstDigitIndex+nDigits-1]&1) != 0 ) {
+ roundup();
+ }
+ } else if ( lowDigitDifference > 0 ){
+ roundup();
+ }
+ } else {
+ roundup();
+ }
+ }
+ }
+
+ // add one to the least significant digit.
+ // in the unlikely event there is a carry out, deal with it.
+ // assert that this will only happen where there
+ // is only one digit, e.g. (float)1e-44 seems to do it.
+ //
+ private void roundup() {
+ int i = (firstDigitIndex + nDigits - 1);
+ int q = digits[i];
+ if (q == '9') {
+ while (q == '9' && i > firstDigitIndex) {
+ digits[i] = '0';
+ q = digits[--i];
+ }
+ if (q == '9') {
+ // carryout! High-order 1, rest 0s, larger exp.
+ decExponent += 1;
+ digits[firstDigitIndex] = '1';
+ return;
+ }
+ // else fall through.
+ }
+ digits[i] = (char) (q + 1);
+ decimalDigitsRoundedUp = true;
+ }
+
+ /**
+ * Estimate decimal exponent. (If it is small-ish,
+ * we could double-check.)
+ *
+ * First, scale the mantissa bits such that 1 <= d2 < 2.
+ * We are then going to estimate
+ * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5)
+ * and so we can estimate
+ * log10(d) ~=~ log10(d2) + binExp * log10(2)
+ * take the floor and call it decExp.
+ */
+ static int estimateDecExp(long fractBits, int binExp) {
+ double d2 = Double.longBitsToDouble( EXP_ONE | ( fractBits & DoubleConsts.SIGNIF_BIT_MASK ) );
+ double d = (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981;
+ long dBits = Double.doubleToRawLongBits(d); //can't be NaN here so use raw
+ int exponent = (int)((dBits & DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT) - DoubleConsts.EXP_BIAS;
+ boolean isNegative = (dBits & DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
+ if(exponent>=0 && exponent<52) { // hot path
+ long mask = DoubleConsts.SIGNIF_BIT_MASK >> exponent;
+ int r = (int)(( (dBits&DoubleConsts.SIGNIF_BIT_MASK) | FRACT_HOB )>>(EXP_SHIFT-exponent));
+ return isNegative ? (((mask & dBits) == 0L ) ? -r : -r-1 ) : r;
+ } else if (exponent < 0) {
+ return (((dBits&~DoubleConsts.SIGN_BIT_MASK) == 0) ? 0 :
+ ( (isNegative) ? -1 : 0) );
+ } else { //if (exponent >= 52)
+ return (int)d;
+ }
+ }
+
+ private static int insignificantDigits(int insignificant) {
+ int i;
+ for ( i = 0; insignificant >= 10L; i++ ) {
+ insignificant /= 10L;
+ }
+ return i;
+ }
+
+ /**
+ * Calculates
+ * <pre>
+ * insignificantDigitsForPow2(v) == insignificantDigits(1L<<v)
+ * </pre>
+ */
+ private static int insignificantDigitsForPow2(int p2) {
+ if(p2>1 && p2 < insignificantDigitsNumber.length) {
+ return insignificantDigitsNumber[p2];
+ }
+ return 0;
+ }
+
+ /**
+ * If insignificant==(1L << ixd)
+ * i = insignificantDigitsNumber[idx] is the same as:
+ * int i;
+ * for ( i = 0; insignificant >= 10L; i++ )
+ * insignificant /= 10L;
+ */
+ private static int[] insignificantDigitsNumber = {
+ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3,
+ 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
+ 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11,
+ 12, 12, 12, 12, 13, 13, 13, 14, 14, 14,
+ 15, 15, 15, 15, 16, 16, 16, 17, 17, 17,
+ 18, 18, 18, 19
+ };
+
+ // approximately ceil( log2( long5pow[i] ) )
+ private static final int[] N_5_BITS = {
+ 0,
+ 3,
+ 5,
+ 7,
+ 10,
+ 12,
+ 14,
+ 17,
+ 19,
+ 21,
+ 24,
+ 26,
+ 28,
+ 31,
+ 33,
+ 35,
+ 38,
+ 40,
+ 42,
+ 45,
+ 47,
+ 49,
+ 52,
+ 54,
+ 56,
+ 59,
+ 61,
+ };
+
+ private int getChars(char[] result) {
+ assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
+ int i = 0;
+ if (isNegative) {
+ result[0] = '-';
+ i = 1;
+ }
+ if (decExponent > 0 && decExponent < 8) {
+ // print digits.digits.
+ int charLength = Math.min(nDigits, decExponent);
+ System.arraycopy(digits, firstDigitIndex, result, i, charLength);
+ i += charLength;
+ if (charLength < decExponent) {
+ charLength = decExponent - charLength;
+ Arrays.fill(result,i,i+charLength,'0');
+ i += charLength;
+ result[i++] = '.';
+ result[i++] = '0';
+ } else {
+ result[i++] = '.';
+ if (charLength < nDigits) {
+ int t = nDigits - charLength;
+ System.arraycopy(digits, firstDigitIndex+charLength, result, i, t);
+ i += t;
+ } else {
+ result[i++] = '0';
+ }
+ }
+ } else if (decExponent <= 0 && decExponent > -3) {
+ result[i++] = '0';
+ result[i++] = '.';
+ if (decExponent != 0) {
+ Arrays.fill(result, i, i-decExponent, '0');
+ i -= decExponent;
+ }
+ System.arraycopy(digits, firstDigitIndex, result, i, nDigits);
+ i += nDigits;
+ } else {
+ result[i++] = digits[firstDigitIndex];
+ result[i++] = '.';
+ if (nDigits > 1) {
+ System.arraycopy(digits, firstDigitIndex+1, result, i, nDigits - 1);
+ i += nDigits - 1;
+ } else {
+ result[i++] = '0';
+ }
+ result[i++] = 'E';
+ int e;
+ if (decExponent <= 0) {
+ result[i++] = '-';
+ e = -decExponent + 1;
+ } else {
+ e = decExponent - 1;
+ }
+ // decExponent has 1, 2, or 3, digits
+ if (e <= 9) {
+ result[i++] = (char) (e + '0');
+ } else if (e <= 99) {
+ result[i++] = (char) (e / 10 + '0');
+ result[i++] = (char) (e % 10 + '0');
+ } else {
+ result[i++] = (char) (e / 100 + '0');
+ e %= 100;
+ result[i++] = (char) (e / 10 + '0');
+ result[i++] = (char) (e % 10 + '0');
+ }
+ }
+ return i;
+ }
+
+ }
+
+ private static final ThreadLocal<BinaryToASCIIBuffer> threadLocalBinaryToASCIIBuffer =
+ new ThreadLocal<BinaryToASCIIBuffer>() {
+ @Override
+ protected BinaryToASCIIBuffer initialValue() {
+ return new BinaryToASCIIBuffer();
+ }
+ };
+
+ private static BinaryToASCIIBuffer getBinaryToASCIIBuffer() {
+ return threadLocalBinaryToASCIIBuffer.get();
+ }
+
+ /**
+ * A converter which can process an ASCII <code>String</code> representation
+ * of a single or double precision floating point value into a
+ * <code>float</code> or a <code>double</code>.
+ */
+ interface ASCIIToBinaryConverter {
+
+ double doubleValue();
+
+ float floatValue();
+
+ }
+
+ /**
+ * A <code>ASCIIToBinaryConverter</code> container for a <code>double</code>.
+ */
+ static class PreparedASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
+ private final double doubleVal;
+ private final float floatVal;
+
+ public PreparedASCIIToBinaryBuffer(double doubleVal, float floatVal) {
+ this.doubleVal = doubleVal;
+ this.floatVal = floatVal;
+ }
+
+ @Override
+ public double doubleValue() {
+ return doubleVal;
+ }
+
+ @Override
+ public float floatValue() {
+ return floatVal;
+ }
+ }
+
+ static final ASCIIToBinaryConverter A2BC_POSITIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
+ static final ASCIIToBinaryConverter A2BC_NEGATIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
+ static final ASCIIToBinaryConverter A2BC_NOT_A_NUMBER = new PreparedASCIIToBinaryBuffer(Double.NaN, Float.NaN);
+ static final ASCIIToBinaryConverter A2BC_POSITIVE_ZERO = new PreparedASCIIToBinaryBuffer(0.0d, 0.0f);
+ static final ASCIIToBinaryConverter A2BC_NEGATIVE_ZERO = new PreparedASCIIToBinaryBuffer(-0.0d, -0.0f);
+
+ /**
+ * A buffered implementation of <code>ASCIIToBinaryConverter</code>.
+ */
+ static class ASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
+ boolean isNegative;
+ int decExponent;
+ char digits[];
+ int nDigits;
+
+ ASCIIToBinaryBuffer( boolean negSign, int decExponent, char[] digits, int n)
+ {
+ this.isNegative = negSign;
+ this.decExponent = decExponent;
+ this.digits = digits;
+ this.nDigits = n;
+ }
+
+ /**
+ * Takes a FloatingDecimal, which we presumably just scanned in,
+ * and finds out what its value is, as a double.
+ *
+ * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
+ * ROUNDING DIRECTION in case the result is really destined
+ * for a single-precision float.
+ */
+ @Override
+ public double doubleValue() {
+ int kDigits = Math.min(nDigits, MAX_DECIMAL_DIGITS + 1);
+ //
+ // convert the lead kDigits to a long integer.
+ //
+ // (special performance hack: start to do it using int)
+ int iValue = (int) digits[0] - (int) '0';
+ int iDigits = Math.min(kDigits, INT_DECIMAL_DIGITS);
+ for (int i = 1; i < iDigits; i++) {
+ iValue = iValue * 10 + (int) digits[i] - (int) '0';
+ }
+ long lValue = (long) iValue;
+ for (int i = iDigits; i < kDigits; i++) {
+ lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
+ }
+ double dValue = (double) lValue;
+ int exp = decExponent - kDigits;
+ //
+ // lValue now contains a long integer with the value of
+ // the first kDigits digits of the number.
+ // dValue contains the (double) of the same.
+ //
+
+ if (nDigits <= MAX_DECIMAL_DIGITS) {
+ //
+ // possibly an easy case.
+ // We know that the digits can be represented
+ // exactly. And if the exponent isn't too outrageous,
+ // the whole thing can be done with one operation,
+ // thus one rounding error.
+ // Note that all our constructors trim all leading and
+ // trailing zeros, so simple values (including zero)
+ // will always end up here
+ //
+ if (exp == 0 || dValue == 0.0) {
+ return (isNegative) ? -dValue : dValue; // small floating integer
+ }
+ else if (exp >= 0) {
+ if (exp <= MAX_SMALL_TEN) {
+ //
+ // Can get the answer with one operation,
+ // thus one roundoff.
+ //
+ double rValue = dValue * SMALL_10_POW[exp];
+ return (isNegative) ? -rValue : rValue;
+ }
+ int slop = MAX_DECIMAL_DIGITS - kDigits;
+ if (exp <= MAX_SMALL_TEN + slop) {
+ //
+ // We can multiply dValue by 10^(slop)
+ // and it is still "small" and exact.
+ // Then we can multiply by 10^(exp-slop)
+ // with one rounding.
+ //
+ dValue *= SMALL_10_POW[slop];
+ double rValue = dValue * SMALL_10_POW[exp - slop];
+ return (isNegative) ? -rValue : rValue;
+ }
+ //
+ // Else we have a hard case with a positive exp.
+ //
+ } else {
+ if (exp >= -MAX_SMALL_TEN) {
+ //
+ // Can get the answer in one division.
+ //
+ double rValue = dValue / SMALL_10_POW[-exp];
+ return (isNegative) ? -rValue : rValue;
+ }
+ //
+ // Else we have a hard case with a negative exp.
+ //
+ }
+ }
+
+ //
+ // Harder cases:
+ // The sum of digits plus exponent is greater than
+ // what we think we can do with one error.
+ //
+ // Start by approximating the right answer by,
+ // naively, scaling by powers of 10.
+ //
+ if (exp > 0) {
+ if (decExponent > MAX_DECIMAL_EXPONENT + 1) {
+ //
+ // Lets face it. This is going to be
+ // Infinity. Cut to the chase.
+ //
+ return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ if ((exp & 15) != 0) {
+ dValue *= SMALL_10_POW[exp & 15];
+ }
+ if ((exp >>= 4) != 0) {
+ int j;
+ for (j = 0; exp > 1; j++, exp >>= 1) {
+ if ((exp & 1) != 0) {
+ dValue *= BIG_10_POW[j];
+ }
+ }
+ //
+ // The reason for the weird exp > 1 condition
+ // in the above loop was so that the last multiply
+ // would get unrolled. We handle it here.
+ // It could overflow.
+ //
+ double t = dValue * BIG_10_POW[j];
+ if (Double.isInfinite(t)) {
+ //
+ // It did overflow.
+ // Look more closely at the result.
+ // If the exponent is just one too large,
+ // then use the maximum finite as our estimate
+ // value. Else call the result infinity
+ // and punt it.
+ // ( I presume this could happen because
+ // rounding forces the result here to be
+ // an ULP or two larger than
+ // Double.MAX_VALUE ).
+ //
+ t = dValue / 2.0;
+ t *= BIG_10_POW[j];
+ if (Double.isInfinite(t)) {
+ return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ t = Double.MAX_VALUE;
+ }
+ dValue = t;
+ }
+ } else if (exp < 0) {
+ exp = -exp;
+ if (decExponent < MIN_DECIMAL_EXPONENT - 1) {
+ //
+ // Lets face it. This is going to be
+ // zero. Cut to the chase.
+ //
+ return (isNegative) ? -0.0 : 0.0;
+ }
+ if ((exp & 15) != 0) {
+ dValue /= SMALL_10_POW[exp & 15];
+ }
+ if ((exp >>= 4) != 0) {
+ int j;
+ for (j = 0; exp > 1; j++, exp >>= 1) {
+ if ((exp & 1) != 0) {
+ dValue *= TINY_10_POW[j];
+ }
+ }
+ //
+ // The reason for the weird exp > 1 condition
+ // in the above loop was so that the last multiply
+ // would get unrolled. We handle it here.
+ // It could underflow.
+ //
+ double t = dValue * TINY_10_POW[j];
+ if (t == 0.0) {
+ //
+ // It did underflow.
+ // Look more closely at the result.
+ // If the exponent is just one too small,
+ // then use the minimum finite as our estimate
+ // value. Else call the result 0.0
+ // and punt it.
+ // ( I presume this could happen because
+ // rounding forces the result here to be
+ // an ULP or two less than
+ // Double.MIN_VALUE ).
+ //
+ t = dValue * 2.0;
+ t *= TINY_10_POW[j];
+ if (t == 0.0) {
+ return (isNegative) ? -0.0 : 0.0;
+ }
+ t = Double.MIN_VALUE;
+ }
+ dValue = t;
+ }
+ }
+
+ //
+ // dValue is now approximately the result.
+ // The hard part is adjusting it, by comparison
+ // with FDBigInteger arithmetic.
+ // Formulate the EXACT big-number result as
+ // bigD0 * 10^exp
+ //
+ if (nDigits > MAX_NDIGITS) {
+ nDigits = MAX_NDIGITS + 1;
+ digits[MAX_NDIGITS] = '1';
+ }
+ FDBigInteger bigD0 = new FDBigInteger(lValue, digits, kDigits, nDigits);
+ exp = decExponent - nDigits;
+
+ long ieeeBits = Double.doubleToRawLongBits(dValue); // IEEE-754 bits of double candidate
+ final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
+ final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
+ bigD0 = bigD0.multByPow52(D5, 0);
+ bigD0.makeImmutable(); // prevent bigD0 modification inside correctionLoop
+ FDBigInteger bigD = null;
+ int prevD2 = 0;
+
+ correctionLoop:
+ while (true) {
+ // here ieeeBits can't be NaN, Infinity or zero
+ int binexp = (int) (ieeeBits >>> EXP_SHIFT);
+ long bigBbits = ieeeBits & DoubleConsts.SIGNIF_BIT_MASK;
+ if (binexp > 0) {
+ bigBbits |= FRACT_HOB;
+ } else { // Normalize denormalized numbers.
+ assert bigBbits != 0L : bigBbits; // doubleToBigInt(0.0)
+ int leadingZeros = Long.numberOfLeadingZeros(bigBbits);
+ int shift = leadingZeros - (63 - EXP_SHIFT);
+ bigBbits <<= shift;
+ binexp = 1 - shift;
+ }
+ binexp -= DoubleConsts.EXP_BIAS;
+ int lowOrderZeros = Long.numberOfTrailingZeros(bigBbits);
+ bigBbits >>>= lowOrderZeros;
+ final int bigIntExp = binexp - EXP_SHIFT + lowOrderZeros;
+ final int bigIntNBits = EXP_SHIFT + 1 - lowOrderZeros;
+
+ //
+ // Scale bigD, bigB appropriately for
+ // big-integer operations.
+ // Naively, we multiply by powers of ten
+ // and powers of two. What we actually do
+ // is keep track of the powers of 5 and
+ // powers of 2 we would use, then factor out
+ // common divisors before doing the work.
+ //
+ int B2 = B5; // powers of 2 in bigB
+ int D2 = D5; // powers of 2 in bigD
+ int Ulp2; // powers of 2 in halfUlp.
+ if (bigIntExp >= 0) {
+ B2 += bigIntExp;
+ } else {
+ D2 -= bigIntExp;
+ }
+ Ulp2 = B2;
+ // shift bigB and bigD left by a number s. t.
+ // halfUlp is still an integer.
+ int hulpbias;
+ if (binexp <= -DoubleConsts.EXP_BIAS) {
+ // This is going to be a denormalized number
+ // (if not actually zero).
+ // half an ULP is at 2^-(DoubleConsts.EXP_BIAS+EXP_SHIFT+1)
+ hulpbias = binexp + lowOrderZeros + DoubleConsts.EXP_BIAS;
+ } else {
+ hulpbias = 1 + lowOrderZeros;
+ }
+ B2 += hulpbias;
+ D2 += hulpbias;
+ // if there are common factors of 2, we might just as well
+ // factor them out, as they add nothing useful.
+ int common2 = Math.min(B2, Math.min(D2, Ulp2));
+ B2 -= common2;
+ D2 -= common2;
+ Ulp2 -= common2;
+ // do multiplications by powers of 5 and 2
+ FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
+ if (bigD == null || prevD2 != D2) {
+ bigD = bigD0.leftShift(D2);
+ prevD2 = D2;
+ }
+ //
+ // to recap:
+ // bigB is the scaled-big-int version of our floating-point
+ // candidate.
+ // bigD is the scaled-big-int version of the exact value
+ // as we understand it.
+ // halfUlp is 1/2 an ulp of bigB, except for special cases
+ // of exact powers of 2
+ //
+ // the plan is to compare bigB with bigD, and if the difference
+ // is less than halfUlp, then we're satisfied. Otherwise,
+ // use the ratio of difference to halfUlp to calculate a fudge
+ // factor to add to the floating value, then go 'round again.
+ //
+ FDBigInteger diff;
+ int cmpResult;
+ boolean overvalue;
+ if ((cmpResult = bigB.cmp(bigD)) > 0) {
+ overvalue = true; // our candidate is too big.
+ diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
+ if ((bigIntNBits == 1) && (bigIntExp > -DoubleConsts.EXP_BIAS + 1)) {
+ // candidate is a normalized exact power of 2 and
+ // is too big (larger than Double.MIN_NORMAL). We will be subtracting.
+ // For our purposes, ulp is the ulp of the
+ // next smaller range.
+ Ulp2 -= 1;
+ if (Ulp2 < 0) {
+ // rats. Cannot de-scale ulp this far.
+ // must scale diff in other direction.
+ Ulp2 = 0;
+ diff = diff.leftShift(1);
+ }
+ }
+ } else if (cmpResult < 0) {
+ overvalue = false; // our candidate is too small.
+ diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
+ } else {
+ // the candidate is exactly right!
+ // this happens with surprising frequency
+ break correctionLoop;
+ }
+ cmpResult = diff.cmpPow52(B5, Ulp2);
+ if ((cmpResult) < 0) {
+ // difference is small.
+ // this is close enough
+ break correctionLoop;
+ } else if (cmpResult == 0) {
+ // difference is exactly half an ULP
+ // round to some other value maybe, then finish
+ if ((ieeeBits & 1) != 0) { // half ties to even
+ ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+ }
+ 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.
+ ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+ if (ieeeBits == 0 || ieeeBits == DoubleConsts.EXP_BIT_MASK) { // 0.0 or Double.POSITIVE_INFINITY
+ break correctionLoop; // oops. Fell off end of range.
+ }
+ continue; // try again.
+ }
+
+ }
+ if (isNegative) {
+ ieeeBits |= DoubleConsts.SIGN_BIT_MASK;
+ }
+ return Double.longBitsToDouble(ieeeBits);
+ }
+
+ /**
+ * Takes a FloatingDecimal, which we presumably just scanned in,
+ * and finds out what its value is, as a float.
+ * This is distinct from doubleValue() to avoid the extremely
+ * unlikely case of a double rounding error, wherein the conversion
+ * to double has one rounding error, and the conversion of that double
+ * to a float has another rounding error, IN THE WRONG DIRECTION,
+ * ( because of the preference to a zero low-order bit ).
+ */
+ @Override
+ public float floatValue() {
+ int kDigits = Math.min(nDigits, SINGLE_MAX_DECIMAL_DIGITS + 1);
+ //
+ // convert the lead kDigits to an integer.
+ //
+ int iValue = (int) digits[0] - (int) '0';
+ for (int i = 1; i < kDigits; i++) {
+ iValue = iValue * 10 + (int) digits[i] - (int) '0';
+ }
+ float fValue = (float) iValue;
+ int exp = decExponent - kDigits;
+ //
+ // iValue now contains an integer with the value of
+ // the first kDigits digits of the number.
+ // fValue contains the (float) of the same.
+ //
+
+ if (nDigits <= SINGLE_MAX_DECIMAL_DIGITS) {
+ //
+ // possibly an easy case.
+ // We know that the digits can be represented
+ // exactly. And if the exponent isn't too outrageous,
+ // the whole thing can be done with one operation,
+ // thus one rounding error.
+ // Note that all our constructors trim all leading and
+ // trailing zeros, so simple values (including zero)
+ // will always end up here.
+ //
+ if (exp == 0 || fValue == 0.0f) {
+ return (isNegative) ? -fValue : fValue; // small floating integer
+ } else if (exp >= 0) {
+ if (exp <= SINGLE_MAX_SMALL_TEN) {
+ //
+ // Can get the answer with one operation,
+ // thus one roundoff.
+ //
+ fValue *= SINGLE_SMALL_10_POW[exp];
+ return (isNegative) ? -fValue : fValue;
+ }
+ int slop = SINGLE_MAX_DECIMAL_DIGITS - kDigits;
+ if (exp <= SINGLE_MAX_SMALL_TEN + slop) {
+ //
+ // We can multiply fValue by 10^(slop)
+ // and it is still "small" and exact.
+ // Then we can multiply by 10^(exp-slop)
+ // with one rounding.
+ //
+ fValue *= SINGLE_SMALL_10_POW[slop];
+ fValue *= SINGLE_SMALL_10_POW[exp - slop];
+ return (isNegative) ? -fValue : fValue;
+ }
+ //
+ // Else we have a hard case with a positive exp.
+ //
+ } else {
+ if (exp >= -SINGLE_MAX_SMALL_TEN) {
+ //
+ // Can get the answer in one division.
+ //
+ fValue /= SINGLE_SMALL_10_POW[-exp];
+ return (isNegative) ? -fValue : fValue;
+ }
+ //
+ // Else we have a hard case with a negative exp.
+ //
+ }
+ } else if ((decExponent >= nDigits) && (nDigits + decExponent <= MAX_DECIMAL_DIGITS)) {
+ //
+ // In double-precision, this is an exact floating integer.
+ // So we can compute to double, then shorten to float
+ // with one round, and get the right answer.
+ //
+ // First, finish accumulating digits.
+ // Then convert that integer to a double, multiply
+ // by the appropriate power of ten, and convert to float.
+ //
+ long lValue = (long) iValue;
+ for (int i = kDigits; i < nDigits; i++) {
+ lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
+ }
+ double dValue = (double) lValue;
+ exp = decExponent - nDigits;
+ dValue *= SMALL_10_POW[exp];
+ fValue = (float) dValue;
+ return (isNegative) ? -fValue : fValue;
+
+ }
+ //
+ // Harder cases:
+ // The sum of digits plus exponent is greater than
+ // what we think we can do with one error.
+ //
+ // Start by approximating the right answer by,
+ // naively, scaling by powers of 10.
+ // Scaling uses doubles to avoid overflow/underflow.
+ //
+ double dValue = fValue;
+ if (exp > 0) {
+ if (decExponent > SINGLE_MAX_DECIMAL_EXPONENT + 1) {
+ //
+ // Lets face it. This is going to be
+ // Infinity. Cut to the chase.
+ //
+ return (isNegative) ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+ }
+ if ((exp & 15) != 0) {
+ dValue *= SMALL_10_POW[exp & 15];
+ }
+ if ((exp >>= 4) != 0) {
+ int j;
+ for (j = 0; exp > 0; j++, exp >>= 1) {
+ if ((exp & 1) != 0) {
+ dValue *= BIG_10_POW[j];
+ }
+ }
+ }
+ } else if (exp < 0) {
+ exp = -exp;
+ if (decExponent < SINGLE_MIN_DECIMAL_EXPONENT - 1) {
+ //
+ // Lets face it. This is going to be
+ // zero. Cut to the chase.
+ //
+ return (isNegative) ? -0.0f : 0.0f;
+ }
+ if ((exp & 15) != 0) {
+ dValue /= SMALL_10_POW[exp & 15];
+ }
+ if ((exp >>= 4) != 0) {
+ int j;
+ for (j = 0; exp > 0; j++, exp >>= 1) {
+ if ((exp & 1) != 0) {
+ dValue *= TINY_10_POW[j];
+ }
+ }
+ }
+ }
+ fValue = Math.max(Float.MIN_VALUE, Math.min(Float.MAX_VALUE, (float) dValue));
+
+ //
+ // fValue is now approximately the result.
+ // The hard part is adjusting it, by comparison
+ // with FDBigInteger arithmetic.
+ // Formulate the EXACT big-number result as
+ // bigD0 * 10^exp
+ //
+ if (nDigits > SINGLE_MAX_NDIGITS) {
+ nDigits = SINGLE_MAX_NDIGITS + 1;
+ digits[SINGLE_MAX_NDIGITS] = '1';
+ }
+ FDBigInteger bigD0 = new FDBigInteger(iValue, digits, kDigits, nDigits);
+ exp = decExponent - nDigits;
+
+ int ieeeBits = Float.floatToRawIntBits(fValue); // IEEE-754 bits of float candidate
+ final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
+ final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
+ bigD0 = bigD0.multByPow52(D5, 0);
+ bigD0.makeImmutable(); // prevent bigD0 modification inside correctionLoop
+ FDBigInteger bigD = null;
+ int prevD2 = 0;
+
+ correctionLoop:
+ while (true) {
+ // here ieeeBits can't be NaN, Infinity or zero
+ int binexp = ieeeBits >>> SINGLE_EXP_SHIFT;
+ int bigBbits = ieeeBits & FloatConsts.SIGNIF_BIT_MASK;
+ if (binexp > 0) {
+ bigBbits |= SINGLE_FRACT_HOB;
+ } else { // Normalize denormalized numbers.
+ assert bigBbits != 0 : bigBbits; // floatToBigInt(0.0)
+ int leadingZeros = Integer.numberOfLeadingZeros(bigBbits);
+ int shift = leadingZeros - (31 - SINGLE_EXP_SHIFT);
+ bigBbits <<= shift;
+ binexp = 1 - shift;
+ }
+ binexp -= FloatConsts.EXP_BIAS;
+ int lowOrderZeros = Integer.numberOfTrailingZeros(bigBbits);
+ bigBbits >>>= lowOrderZeros;
+ final int bigIntExp = binexp - SINGLE_EXP_SHIFT + lowOrderZeros;
+ final int bigIntNBits = SINGLE_EXP_SHIFT + 1 - lowOrderZeros;
+
+ //
+ // Scale bigD, bigB appropriately for
+ // big-integer operations.
+ // Naively, we multiply by powers of ten
+ // and powers of two. What we actually do
+ // is keep track of the powers of 5 and
+ // powers of 2 we would use, then factor out
+ // common divisors before doing the work.
+ //
+ int B2 = B5; // powers of 2 in bigB
+ int D2 = D5; // powers of 2 in bigD
+ int Ulp2; // powers of 2 in halfUlp.
+ if (bigIntExp >= 0) {
+ B2 += bigIntExp;
+ } else {
+ D2 -= bigIntExp;
+ }
+ Ulp2 = B2;
+ // shift bigB and bigD left by a number s. t.
+ // halfUlp is still an integer.
+ int hulpbias;
+ if (binexp <= -FloatConsts.EXP_BIAS) {
+ // This is going to be a denormalized number
+ // (if not actually zero).
+ // half an ULP is at 2^-(FloatConsts.EXP_BIAS+SINGLE_EXP_SHIFT+1)
+ hulpbias = binexp + lowOrderZeros + FloatConsts.EXP_BIAS;
+ } else {
+ hulpbias = 1 + lowOrderZeros;
+ }
+ B2 += hulpbias;
+ D2 += hulpbias;
+ // if there are common factors of 2, we might just as well
+ // factor them out, as they add nothing useful.
+ int common2 = Math.min(B2, Math.min(D2, Ulp2));
+ B2 -= common2;
+ D2 -= common2;
+ Ulp2 -= common2;
+ // do multiplications by powers of 5 and 2
+ FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
+ if (bigD == null || prevD2 != D2) {
+ bigD = bigD0.leftShift(D2);
+ prevD2 = D2;
+ }
+ //
+ // to recap:
+ // bigB is the scaled-big-int version of our floating-point
+ // candidate.
+ // bigD is the scaled-big-int version of the exact value
+ // as we understand it.
+ // halfUlp is 1/2 an ulp of bigB, except for special cases
+ // of exact powers of 2
+ //
+ // the plan is to compare bigB with bigD, and if the difference
+ // is less than halfUlp, then we're satisfied. Otherwise,
+ // use the ratio of difference to halfUlp to calculate a fudge
+ // factor to add to the floating value, then go 'round again.
+ //
+ FDBigInteger diff;
+ int cmpResult;
+ boolean overvalue;
+ if ((cmpResult = bigB.cmp(bigD)) > 0) {
+ overvalue = true; // our candidate is too big.
+ diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
+ if ((bigIntNBits == 1) && (bigIntExp > -FloatConsts.EXP_BIAS + 1)) {
+ // candidate is a normalized exact power of 2 and
+ // is too big (larger than Float.MIN_NORMAL). We will be subtracting.
+ // For our purposes, ulp is the ulp of the
+ // next smaller range.
+ Ulp2 -= 1;
+ if (Ulp2 < 0) {
+ // rats. Cannot de-scale ulp this far.
+ // must scale diff in other direction.
+ Ulp2 = 0;
+ diff = diff.leftShift(1);
+ }
+ }
+ } else if (cmpResult < 0) {
+ overvalue = false; // our candidate is too small.
+ diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
+ } else {
+ // the candidate is exactly right!
+ // this happens with surprising frequency
+ break correctionLoop;
+ }
+ cmpResult = diff.cmpPow52(B5, Ulp2);
+ if ((cmpResult) < 0) {
+ // difference is small.
+ // this is close enough
+ break correctionLoop;
+ } else if (cmpResult == 0) {
+ // difference is exactly half an ULP
+ // round to some other value maybe, then finish
+ if ((ieeeBits & 1) != 0) { // half ties to even
+ ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+ }
+ 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.
+ ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+ if (ieeeBits == 0 || ieeeBits == FloatConsts.EXP_BIT_MASK) { // 0.0 or Float.POSITIVE_INFINITY
+ break correctionLoop; // oops. Fell off end of range.
+ }
+ continue; // try again.
+ }
+
+ }
+ if (isNegative) {
+ ieeeBits |= FloatConsts.SIGN_BIT_MASK;
+ }
+ return Float.intBitsToFloat(ieeeBits);
+ }
+
+
+ /**
+ * All the positive powers of 10 that can be
+ * represented exactly in double/float.
+ */
+ private static final double[] SMALL_10_POW = {
+ 1.0e0,
+ 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
+ 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
+ 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
+ 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
+ 1.0e21, 1.0e22
+ };
+
+ private static final float[] SINGLE_SMALL_10_POW = {
+ 1.0e0f,
+ 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
+ 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
+ };
+
+ private static final double[] BIG_10_POW = {
+ 1e16, 1e32, 1e64, 1e128, 1e256 };
+ private static final double[] TINY_10_POW = {
+ 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
+
+ private static final int MAX_SMALL_TEN = SMALL_10_POW.length-1;
+ private static final int SINGLE_MAX_SMALL_TEN = SINGLE_SMALL_10_POW.length-1;
+
+ }
+
+ /**
+ * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
+ * The returned object is a <code>ThreadLocal</code> variable of this class.
+ *
+ * @param d The double precision value to convert.
+ * @return The converter.
+ */
+ public static BinaryToASCIIConverter getBinaryToASCIIConverter(double d) {
+ return getBinaryToASCIIConverter(d, true);
+ }
+
+ /**
+ * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
+ * The returned object is a <code>ThreadLocal</code> variable of this class.
+ *
+ * @param d The double precision value to convert.
+ * @param isCompatibleFormat
+ * @return The converter.
+ */
+ static BinaryToASCIIConverter getBinaryToASCIIConverter(double d, boolean isCompatibleFormat) {
+ long dBits = Double.doubleToRawLongBits(d);
+ boolean isNegative = (dBits&DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
+ long fractBits = dBits & DoubleConsts.SIGNIF_BIT_MASK;
+ int binExp = (int)( (dBits&DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT );
+ // Discover obvious special cases of NaN and Infinity.
+ if ( binExp == (int)(DoubleConsts.EXP_BIT_MASK>>EXP_SHIFT) ) {
+ if ( fractBits == 0L ){
+ return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
+ } else {
+ return B2AC_NOT_A_NUMBER;
+ }
+ }
+ // Finish unpacking
+ // Normalize denormalized numbers.
+ // Insert assumed high-order bit for normalized numbers.
+ // Subtract exponent bias.
+ int nSignificantBits;
+ if ( binExp == 0 ){
+ if ( fractBits == 0L ){
+ // not a denorm, just a 0!
+ return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
+ }
+ int leadingZeros = Long.numberOfLeadingZeros(fractBits);
+ int shift = leadingZeros-(63-EXP_SHIFT);
+ fractBits <<= shift;
+ binExp = 1 - shift;
+ nSignificantBits = 64-leadingZeros; // recall binExp is - shift count.
+ } else {
+ fractBits |= FRACT_HOB;
+ nSignificantBits = EXP_SHIFT+1;
+ }
+ binExp -= DoubleConsts.EXP_BIAS;
+ BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
+ buf.setSign(isNegative);
+ // call the routine that actually does all the hard work.
+ buf.dtoa(binExp, fractBits, nSignificantBits, isCompatibleFormat);
+ return buf;
+ }
+
+ private static BinaryToASCIIConverter getBinaryToASCIIConverter(float f) {
+ int fBits = Float.floatToRawIntBits( f );
+ boolean isNegative = (fBits&FloatConsts.SIGN_BIT_MASK) != 0;
+ int fractBits = fBits&FloatConsts.SIGNIF_BIT_MASK;
+ int binExp = (fBits&FloatConsts.EXP_BIT_MASK) >> SINGLE_EXP_SHIFT;
+ // Discover obvious special cases of NaN and Infinity.
+ if ( binExp == (FloatConsts.EXP_BIT_MASK>>SINGLE_EXP_SHIFT) ) {
+ if ( fractBits == 0L ){
+ return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
+ } else {
+ return B2AC_NOT_A_NUMBER;
+ }
+ }
+ // Finish unpacking
+ // Normalize denormalized numbers.
+ // Insert assumed high-order bit for normalized numbers.
+ // Subtract exponent bias.
+ int nSignificantBits;
+ if ( binExp == 0 ){
+ if ( fractBits == 0 ){
+ // not a denorm, just a 0!
+ return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
+ }
+ int leadingZeros = Integer.numberOfLeadingZeros(fractBits);
+ int shift = leadingZeros-(31-SINGLE_EXP_SHIFT);
+ fractBits <<= shift;
+ binExp = 1 - shift;
+ nSignificantBits = 32 - leadingZeros; // recall binExp is - shift count.
+ } else {
+ fractBits |= SINGLE_FRACT_HOB;
+ nSignificantBits = SINGLE_EXP_SHIFT+1;
+ }
+ binExp -= FloatConsts.EXP_BIAS;
+ BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
+ buf.setSign(isNegative);
+ // call the routine that actually does all the hard work.
+ buf.dtoa(binExp, ((long)fractBits)<<(EXP_SHIFT-SINGLE_EXP_SHIFT), nSignificantBits, true);
+ return buf;
+ }
+
+ @SuppressWarnings("fallthrough")
+ static ASCIIToBinaryConverter readJavaFormatString( String in ) throws NumberFormatException {
+ boolean isNegative = false;
+ boolean signSeen = false;
+ int decExp;
+ char c;
+
+ parseNumber:
+ try{
+ in = in.trim(); // don't fool around with white space.
+ // throws NullPointerException if null
+ int len = in.length();
+ if ( len == 0 ) {
+ throw new NumberFormatException("empty String");
+ }
+ int i = 0;
+ switch (in.charAt(i)){
+ case '-':
+ isNegative = true;
+ //FALLTHROUGH
+ case '+':
+ i++;
+ signSeen = true;
+ }
+ c = in.charAt(i);
+ if(c == 'N') { // Check for NaN
+ if((len-i)==NAN_LENGTH && in.indexOf(NAN_REP,i)==i) {
+ return A2BC_NOT_A_NUMBER;
+ }
+ // something went wrong, throw exception
+ break parseNumber;
+ } else if(c == 'I') { // Check for Infinity strings
+ if((len-i)==INFINITY_LENGTH && in.indexOf(INFINITY_REP,i)==i) {
+ return isNegative? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
+ }
+ // something went wrong, throw exception
+ break parseNumber;
+ } else if (c == '0') { // check for hexadecimal floating-point number
+ if (len > i+1 ) {
+ char ch = in.charAt(i+1);
+ if (ch == 'x' || ch == 'X' ) { // possible hex string
+ return parseHexString(in);
+ }
+ }
+ } // look for and process decimal floating-point string
+
+ char[] digits = new char[ len ];
+ int nDigits= 0;
+ boolean decSeen = false;
+ int decPt = 0;
+ int nLeadZero = 0;
+ int nTrailZero= 0;
+
+ skipLeadingZerosLoop:
+ while (i < len) {
+ c = in.charAt(i);
+ if (c == '0') {
+ nLeadZero++;
+ } else if (c == '.') {
+ if (decSeen) {
+ // already saw one ., this is the 2nd.
+ throw new NumberFormatException("multiple points");
+ }
+ decPt = i;
+ if (signSeen) {
+ decPt -= 1;
+ }
+ decSeen = true;
+ } else {
+ break skipLeadingZerosLoop;
+ }
+ i++;
+ }
+ digitLoop:
+ while (i < len) {
+ c = in.charAt(i);
+ if (c >= '1' && c <= '9') {
+ digits[nDigits++] = c;
+ nTrailZero = 0;
+ } else if (c == '0') {
+ digits[nDigits++] = c;
+ nTrailZero++;
+ } else if (c == '.') {
+ if (decSeen) {
+ // already saw one ., this is the 2nd.
+ throw new NumberFormatException("multiple points");
+ }
+ decPt = i;
+ if (signSeen) {
+ decPt -= 1;
+ }
+ decSeen = true;
+ } else {
+ break digitLoop;
+ }
+ i++;
+ }
+ nDigits -=nTrailZero;
+ //
+ // At this point, we've scanned all the digits and decimal
+ // point we're going to see. Trim off leading and trailing
+ // zeros, which will just confuse us later, and adjust
+ // our initial decimal exponent accordingly.
+ // To review:
+ // we have seen i total characters.
+ // nLeadZero of them were zeros before any other digits.
+ // nTrailZero of them were zeros after any other digits.
+ // if ( decSeen ), then a . was seen after decPt characters
+ // ( including leading zeros which have been discarded )
+ // nDigits characters were neither lead nor trailing
+ // zeros, nor point
+ //
+ //
+ // special hack: if we saw no non-zero digits, then the
+ // answer is zero!
+ // Unfortunately, we feel honor-bound to keep parsing!
+ //
+ boolean isZero = (nDigits == 0);
+ if ( isZero && nLeadZero == 0 ){
+ // we saw NO DIGITS AT ALL,
+ // not even a crummy 0!
+ // this is not allowed.
+ break parseNumber; // go throw exception
+ }
+ //
+ // Our initial exponent is decPt, adjusted by the number of
+ // discarded zeros. Or, if there was no decPt,
+ // then its just nDigits adjusted by discarded trailing zeros.
+ //
+ if ( decSeen ){
+ decExp = decPt - nLeadZero;
+ } else {
+ decExp = nDigits + nTrailZero;
+ }
+
+ //
+ // Look for 'e' or 'E' and an optionally signed integer.
+ //
+ if ( (i < len) && (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
+ int expSign = 1;
+ int expVal = 0;
+ int reallyBig = Integer.MAX_VALUE / 10;
+ boolean expOverflow = false;
+ switch( in.charAt(++i) ){
+ case '-':
+ expSign = -1;
+ //FALLTHROUGH
+ case '+':
+ i++;
+ }
+ int expAt = i;
+ expLoop:
+ while ( i < len ){
+ if ( expVal >= reallyBig ){
+ // the next character will cause integer
+ // overflow.
+ expOverflow = true;
+ }
+ c = in.charAt(i++);
+ if(c>='0' && c<='9') {
+ expVal = expVal*10 + ( (int)c - (int)'0' );
+ } else {
+ i--; // back up.
+ break expLoop; // stop parsing exponent.
+ }
+ }
+ int expLimit = BIG_DECIMAL_EXPONENT + nDigits + nTrailZero;
+ if (expOverflow || (expVal > expLimit)) {
+ // There is still a chance that the exponent will be safe to
+ // use: if it would eventually decrease due to a negative
+ // decExp, and that number is below the limit. We check for
+ // that here.
+ if (!expOverflow && (expSign == 1 && decExp < 0)
+ && (expVal + decExp) < expLimit) {
+ // Cannot overflow: adding a positive and negative number.
+ decExp += expVal;
+ } else {
+ //
+ // The intent here is to end up with
+ // infinity or zero, as appropriate.
+ // The reason for yielding such a small decExponent,
+ // rather than something intuitive such as
+ // expSign*Integer.MAX_VALUE, is that this value
+ // is subject to further manipulation in
+ // doubleValue() and floatValue(), and I don't want
+ // it to be able to cause overflow there!
+ // (The only way we can get into trouble here is for
+ // really outrageous nDigits+nTrailZero, such as 2
+ // billion.)
+ //
+ decExp = expSign * expLimit;
+ }
+ } else {
+ // this should not overflow, since we tested
+ // for expVal > (MAX+N), where N >= abs(decExp)
+ decExp = decExp + expSign*expVal;
+ }
+
+ // if we saw something not a digit ( or end of string )
+ // after the [Ee][+-], without seeing any digits at all
+ // this is certainly an error. If we saw some digits,
+ // but then some trailing garbage, that might be ok.
+ // so we just fall through in that case.
+ // HUMBUG
+ if ( i == expAt ) {
+ break parseNumber; // certainly bad
+ }
+ }
+ //
+ // We parsed everything we could.
+ // If there are leftovers, then this is not good input!
+ //
+ if ( i < len &&
+ ((i != len - 1) ||
+ (in.charAt(i) != 'f' &&
+ in.charAt(i) != 'F' &&
+ in.charAt(i) != 'd' &&
+ in.charAt(i) != 'D'))) {
+ break parseNumber; // go throw exception
+ }
+ if(isZero) {
+ return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+ }
+ return new ASCIIToBinaryBuffer(isNegative, decExp, digits, nDigits);
+ } catch ( StringIndexOutOfBoundsException e ){ }
+ throw new NumberFormatException("For input string: \"" + in + "\"");
+ }
+
+ private static class HexFloatPattern {
+ /**
+ * Grammar is compatible with hexadecimal floating-point constants
+ * described in section 6.4.4.2 of the C99 specification.
+ */
+ private static final Pattern VALUE = Pattern.compile(
+ //1 234 56 7 8 9
+ "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
+ );
+ }
+
+ /**
+ * Converts string s to a suitable floating decimal; uses the
+ * double constructor and sets the roundDir variable appropriately
+ * in case the value is later converted to a float.
+ *
+ * @param s The <code>String</code> to parse.
+ */
+ static ASCIIToBinaryConverter parseHexString(String s) {
+ // Verify string is a member of the hexadecimal floating-point
+ // string language.
+ Matcher m = HexFloatPattern.VALUE.matcher(s);
+ boolean validInput = m.matches();
+ if (!validInput) {
+ // Input does not match pattern
+ throw new NumberFormatException("For input string: \"" + s + "\"");
+ } else { // validInput
+ //
+ // We must isolate the sign, significand, and exponent
+ // fields. The sign value is straightforward. Since
+ // floating-point numbers are stored with a normalized
+ // representation, the significand and exponent are
+ // interrelated.
+ //
+ // After extracting the sign, we normalized the
+ // significand as a hexadecimal value, calculating an
+ // exponent adjust for any shifts made during
+ // normalization. If the significand is zero, the
+ // exponent doesn't need to be examined since the output
+ // will be zero.
+ //
+ // Next the exponent in the input string is extracted.
+ // Afterwards, the significand is normalized as a *binary*
+ // value and the input value's normalized exponent can be
+ // computed. The significand bits are copied into a
+ // double significand; if the string has more logical bits
+ // than can fit in a double, the extra bits affect the
+ // round and sticky bits which are used to round the final
+ // value.
+ //
+ // Extract significand sign
+ String group1 = m.group(1);
+ boolean isNegative = ((group1 != null) && group1.equals("-"));
+
+ // Extract Significand magnitude
+ //
+ // Based on the form of the significand, calculate how the
+ // binary exponent needs to be adjusted to create a
+ // normalized//hexadecimal* floating-point number; that
+ // is, a number where there is one nonzero hex digit to
+ // the left of the (hexa)decimal point. Since we are
+ // adjusting a binary, not hexadecimal exponent, the
+ // exponent is adjusted by a multiple of 4.
+ //
+ // There are a number of significand scenarios to consider;
+ // letters are used in indicate nonzero digits:
+ //
+ // 1. 000xxxx => x.xxx normalized
+ // increase exponent by (number of x's - 1)*4
+ //
+ // 2. 000xxx.yyyy => x.xxyyyy normalized
+ // increase exponent by (number of x's - 1)*4
+ //
+ // 3. .000yyy => y.yy normalized
+ // decrease exponent by (number of zeros + 1)*4
+ //
+ // 4. 000.00000yyy => y.yy normalized
+ // decrease exponent by (number of zeros to right of point + 1)*4
+ //
+ // If the significand is exactly zero, return a properly
+ // signed zero.
+ //
+
+ String significandString = null;
+ int signifLength = 0;
+ int exponentAdjust = 0;
+ {
+ int leftDigits = 0; // number of meaningful digits to
+ // left of "decimal" point
+ // (leading zeros stripped)
+ int rightDigits = 0; // number of digits to right of
+ // "decimal" point; leading zeros
+ // must always be accounted for
+ //
+ // The significand is made up of either
+ //
+ // 1. group 4 entirely (integer portion only)
+ //
+ // OR
+ //
+ // 2. the fractional portion from group 7 plus any
+ // (optional) integer portions from group 6.
+ //
+ String group4;
+ if ((group4 = m.group(4)) != null) { // Integer-only significand
+ // Leading zeros never matter on the integer portion
+ significandString = stripLeadingZeros(group4);
+ leftDigits = significandString.length();
+ } else {
+ // Group 6 is the optional integer; leading zeros
+ // never matter on the integer portion
+ String group6 = stripLeadingZeros(m.group(6));
+ leftDigits = group6.length();
+
+ // fraction
+ String group7 = m.group(7);
+ rightDigits = group7.length();
+
+ // Turn "integer.fraction" into "integer"+"fraction"
+ significandString =
+ ((group6 == null) ? "" : group6) + // is the null
+ // check necessary?
+ group7;
+ }
+
+ significandString = stripLeadingZeros(significandString);
+ signifLength = significandString.length();
+
+ //
+ // Adjust exponent as described above
+ //
+ if (leftDigits >= 1) { // Cases 1 and 2
+ exponentAdjust = 4 * (leftDigits - 1);
+ } else { // Cases 3 and 4
+ exponentAdjust = -4 * (rightDigits - signifLength + 1);
+ }
+
+ // If the significand is zero, the exponent doesn't
+ // matter; return a properly signed zero.
+
+ if (signifLength == 0) { // Only zeros in input
+ return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+ }
+ }
+
+ // Extract Exponent
+ //
+ // Use an int to read in the exponent value; this should
+ // provide more than sufficient range for non-contrived
+ // inputs. If reading the exponent in as an int does
+ // overflow, examine the sign of the exponent and
+ // significand to determine what to do.
+ //
+ String group8 = m.group(8);
+ boolean positiveExponent = (group8 == null) || group8.equals("+");
+ long unsignedRawExponent;
+ try {
+ unsignedRawExponent = Integer.parseInt(m.group(9));
+ }
+ catch (NumberFormatException e) {
+ // At this point, we know the exponent is
+ // syntactically well-formed as a sequence of
+ // digits. Therefore, if an NumberFormatException
+ // is thrown, it must be due to overflowing int's
+ // range. Also, at this point, we have already
+ // checked for a zero significand. Thus the signs
+ // of the exponent and significand determine the
+ // final result:
+ //
+ // significand
+ // + -
+ // exponent + +infinity -infinity
+ // - +0.0 -0.0
+ return isNegative ?
+ (positiveExponent ? A2BC_NEGATIVE_INFINITY : A2BC_NEGATIVE_ZERO)
+ : (positiveExponent ? A2BC_POSITIVE_INFINITY : A2BC_POSITIVE_ZERO);
+
+ }
+
+ long rawExponent =
+ (positiveExponent ? 1L : -1L) * // exponent sign
+ unsignedRawExponent; // exponent magnitude
+
+ // Calculate partially adjusted exponent
+ long exponent = rawExponent + exponentAdjust;
+
+ // Starting copying non-zero bits into proper position in
+ // a long; copy explicit bit too; this will be masked
+ // later for normal values.
+
+ boolean round = false;
+ boolean sticky = false;
+ int nextShift = 0;
+ long significand = 0L;
+ // First iteration is different, since we only copy
+ // from the leading significand bit; one more exponent
+ // adjust will be needed...
+
+ // IMPORTANT: make leadingDigit a long to avoid
+ // surprising shift semantics!
+ long leadingDigit = getHexDigit(significandString, 0);
+
+ //
+ // Left shift the leading digit (53 - (bit position of
+ // leading 1 in digit)); this sets the top bit of the
+ // significand to 1. The nextShift value is adjusted
+ // to take into account the number of bit positions of
+ // the leadingDigit actually used. Finally, the
+ // exponent is adjusted to normalize the significand
+ // as a binary value, not just a hex value.
+ //
+ if (leadingDigit == 1) {
+ significand |= leadingDigit << 52;
+ nextShift = 52 - 4;
+ // exponent += 0
+ } else if (leadingDigit <= 3) { // [2, 3]
+ significand |= leadingDigit << 51;
+ nextShift = 52 - 5;
+ exponent += 1;
+ } else if (leadingDigit <= 7) { // [4, 7]
+ significand |= leadingDigit << 50;
+ nextShift = 52 - 6;
+ exponent += 2;
+ } else if (leadingDigit <= 15) { // [8, f]
+ significand |= leadingDigit << 49;
+ nextShift = 52 - 7;
+ exponent += 3;
+ } else {
+ throw new AssertionError("Result from digit conversion too large!");
+ }
+ // The preceding if-else could be replaced by a single
+ // code block based on the high-order bit set in
+ // leadingDigit. Given leadingOnePosition,
+
+ // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
+ // nextShift = 52 - (3 + leadingOnePosition);
+ // exponent += (leadingOnePosition-1);
+
+ //
+ // Now the exponent variable is equal to the normalized
+ // binary exponent. Code below will make representation
+ // adjustments if the exponent is incremented after
+ // rounding (includes overflows to infinity) or if the
+ // result is subnormal.
+ //
+
+ // Copy digit into significand until the significand can't
+ // hold another full hex digit or there are no more input
+ // hex digits.
+ int i = 0;
+ for (i = 1;
+ i < signifLength && nextShift >= 0;
+ i++) {
+ long currentDigit = getHexDigit(significandString, i);
+ significand |= (currentDigit << nextShift);
+ nextShift -= 4;
+ }
+
+ // After the above loop, the bulk of the string is copied.
+ // Now, we must copy any partial hex digits into the
+ // significand AND compute the round bit and start computing
+ // sticky bit.
+
+ if (i < signifLength) { // at least one hex input digit exists
+ long currentDigit = getHexDigit(significandString, i);
+
+ // from nextShift, figure out how many bits need
+ // to be copied, if any
+ switch (nextShift) { // must be negative
+ case -1:
+ // three bits need to be copied in; can
+ // set round bit
+ significand |= ((currentDigit & 0xEL) >> 1);
+ round = (currentDigit & 0x1L) != 0L;
+ break;
+
+ case -2:
+ // two bits need to be copied in; can
+ // set round and start sticky
+ significand |= ((currentDigit & 0xCL) >> 2);
+ round = (currentDigit & 0x2L) != 0L;
+ sticky = (currentDigit & 0x1L) != 0;
+ break;
+
+ case -3:
+ // one bit needs to be copied in
+ significand |= ((currentDigit & 0x8L) >> 3);
+ // Now set round and start sticky, if possible
+ round = (currentDigit & 0x4L) != 0L;
+ sticky = (currentDigit & 0x3L) != 0;
+ break;
+
+ case -4:
+ // all bits copied into significand; set
+ // round and start sticky
+ round = ((currentDigit & 0x8L) != 0); // is top bit set?
+ // nonzeros in three low order bits?
+ sticky = (currentDigit & 0x7L) != 0;
+ break;
+
+ default:
+ throw new AssertionError("Unexpected shift distance remainder.");
+ // break;
+ }
+
+ // Round is set; sticky might be set.
+
+ // For the sticky bit, it suffices to check the
+ // current digit and test for any nonzero digits in
+ // the remaining unprocessed input.
+ i++;
+ while (i < signifLength && !sticky) {
+ currentDigit = getHexDigit(significandString, i);
+ sticky = sticky || (currentDigit != 0);
+ i++;
+ }
+
+ }
+ // else all of string was seen, round and sticky are
+ // correct as false.
+
+ // Float calculations
+ int floatBits = isNegative ? FloatConsts.SIGN_BIT_MASK : 0;
+ if (exponent >= FloatConsts.MIN_EXPONENT) {
+ if (exponent > FloatConsts.MAX_EXPONENT) {
+ // Float.POSITIVE_INFINITY
+ floatBits |= FloatConsts.EXP_BIT_MASK;
+ } else {
+ int threshShift = DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH - 1;
+ boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
+ int iValue = (int) (significand >>> threshShift);
+ if ((iValue & 3) != 1 || floatSticky) {
+ iValue++;
+ }
+ floatBits |= (((((int) exponent) + (FloatConsts.EXP_BIAS - 1))) << SINGLE_EXP_SHIFT) + (iValue >> 1);
+ }
+ } else {
+ if (exponent < FloatConsts.MIN_SUB_EXPONENT - 1) {
+ // 0
+ } else {
+ // exponent == -127 ==> threshShift = 53 - 2 + (-149) - (-127) = 53 - 24
+ int threshShift = (int) ((DoubleConsts.SIGNIFICAND_WIDTH - 2 + FloatConsts.MIN_SUB_EXPONENT) - exponent);
+ assert threshShift >= DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH;
+ assert threshShift < DoubleConsts.SIGNIFICAND_WIDTH;
+ boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
+ int iValue = (int) (significand >>> threshShift);
+ if ((iValue & 3) != 1 || floatSticky) {
+ iValue++;
+ }
+ floatBits |= iValue >> 1;
+ }
+ }
+ float fValue = Float.intBitsToFloat(floatBits);
+
+ // Check for overflow and update exponent accordingly.
+ if (exponent > DoubleConsts.MAX_EXPONENT) { // Infinite result
+ // overflow to properly signed infinity
+ return isNegative ? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
+ } else { // Finite return value
+ if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result
+ exponent >= DoubleConsts.MIN_EXPONENT) {
+
+ // The result returned in this block cannot be a
+ // zero or subnormal; however after the
+ // significand is adjusted from rounding, we could
+ // still overflow in infinity.
+
+ // AND exponent bits into significand; if the
+ // significand is incremented and overflows from
+ // rounding, this combination will update the
+ // exponent correctly, even in the case of
+ // Double.MAX_VALUE overflowing to infinity.
+
+ significand = ((( exponent +
+ (long) DoubleConsts.EXP_BIAS) <<
+ (DoubleConsts.SIGNIFICAND_WIDTH - 1))
+ & DoubleConsts.EXP_BIT_MASK) |
+ (DoubleConsts.SIGNIF_BIT_MASK & significand);
+
+ } else { // Subnormal or zero
+ // (exponent < DoubleConsts.MIN_EXPONENT)
+
+ if (exponent < (DoubleConsts.MIN_SUB_EXPONENT - 1)) {
+ // No way to round back to nonzero value
+ // regardless of significand if the exponent is
+ // less than -1075.
+ return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+ } else { // -1075 <= exponent <= MIN_EXPONENT -1 = -1023
+ //
+ // Find bit position to round to; recompute
+ // round and sticky bits, and shift
+ // significand right appropriately.
+ //
+
+ sticky = sticky || round;
+ round = false;
+
+ // Number of bits of significand to preserve is
+ // exponent - abs_min_exp +1
+ // check:
+ // -1075 +1074 + 1 = 0
+ // -1023 +1074 + 1 = 52
+
+ int bitsDiscarded = 53 -
+ ((int) exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
+ assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
+
+ // What to do here:
+ // First, isolate the new round bit
+ round = (significand & (1L << (bitsDiscarded - 1))) != 0L;
+ if (bitsDiscarded > 1) {
+ // create mask to update sticky bits; low
+ // order bitsDiscarded bits should be 1
+ long mask = ~((~0L) << (bitsDiscarded - 1));
+ sticky = sticky || ((significand & mask) != 0L);
+ }
+
+ // Now, discard the bits
+ significand = significand >> bitsDiscarded;
+
+ significand = ((((long) (DoubleConsts.MIN_EXPONENT - 1) + // subnorm exp.
+ (long) DoubleConsts.EXP_BIAS) <<
+ (DoubleConsts.SIGNIFICAND_WIDTH - 1))
+ & DoubleConsts.EXP_BIT_MASK) |
+ (DoubleConsts.SIGNIF_BIT_MASK & significand);
+ }
+ }
+
+ // The significand variable now contains the currently
+ // appropriate exponent bits too.
+
+ //
+ // Determine if significand should be incremented;
+ // making this determination depends on the least
+ // significant bit and the round and sticky bits.
+ //
+ // Round to nearest even rounding table, adapted from
+ // table 4.7 in "Computer Arithmetic" by IsraelKoren.
+ // The digit to the left of the "decimal" point is the
+ // least significant bit, the digits to the right of
+ // the point are the round and sticky bits
+ //
+ // Number Round(x)
+ // x0.00 x0.
+ // x0.01 x0.
+ // x0.10 x0.
+ // x0.11 x1. = x0. +1
+ // x1.00 x1.
+ // x1.01 x1.
+ // x1.10 x1. + 1
+ // x1.11 x1. + 1
+ //
+ boolean leastZero = ((significand & 1L) == 0L);
+ if ((leastZero && round && sticky) ||
+ ((!leastZero) && round)) {
+ significand++;
+ }
+
+ double value = isNegative ?
+ Double.longBitsToDouble(significand | DoubleConsts.SIGN_BIT_MASK) :
+ Double.longBitsToDouble(significand );
+
+ return new PreparedASCIIToBinaryBuffer(value, fValue);
+ }
+ }
+ }
+
+ /**
+ * Returns <code>s</code> with any leading zeros removed.
+ */
+ static String stripLeadingZeros(String s) {
+// return s.replaceFirst("^0+", "");
+ if(!s.isEmpty() && s.charAt(0)=='0') {
+ for(int i=1; i<s.length(); i++) {
+ if(s.charAt(i)!='0') {
+ return s.substring(i);
+ }
+ }
+ return "";
+ }
+ return s;
+ }
+
+ /**
+ * Extracts a hexadecimal digit from position <code>position</code>
+ * of string <code>s</code>.
+ */
+ static int getHexDigit(String s, int position) {
+ int value = Character.digit(s.charAt(position), 16);
+ if (value <= -1 || value >= 16) {
+ throw new AssertionError("Unexpected failure of digit conversion of " +
+ s.charAt(position));
+ }
+ return value;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/math/FormattedFloatingDecimal.java Tue Dec 22 12:17:25 2015 +0000
@@ -0,0 +1,349 @@
+/*
+ * 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
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.math;
+
+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') };
+ }
+ }
+}
--- a/jdk/src/java.base/share/classes/sun/misc/DoubleConsts.java Tue Dec 22 11:07:17 2015 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-/**
- * This class contains additional constants documenting limits of the
- * <code>double</code> type.
- *
- * @author Joseph D. Darcy
- */
-
-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..
- */
- 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)));
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/FDBigInteger.java Tue Dec 22 11:07:17 2015 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1508 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.misc;
-
-import java.math.BigInteger;
-import java.util.Arrays;
-//@ model import org.jmlspecs.models.JMLMath;
-
-/**
- * A simple big integer package specifically for floating point base conversion.
- */
-public /*@ spec_bigint_math @*/ class FDBigInteger {
-
- //
- // This class contains many comments that start with "/*@" mark.
- // They are behavourial specification in
- // the Java Modelling Language (JML):
- // http://www.eecs.ucf.edu/~leavens/JML//index.shtml
- //
-
- /*@
- @ public pure model static \bigint UNSIGNED(int v) {
- @ return v >= 0 ? v : v + (((\bigint)1) << 32);
- @ }
- @
- @ public pure model static \bigint UNSIGNED(long v) {
- @ return v >= 0 ? v : v + (((\bigint)1) << 64);
- @ }
- @
- @ public pure model static \bigint AP(int[] data, int len) {
- @ return (\sum int i; 0 <= 0 && i < len; UNSIGNED(data[i]) << (i*32));
- @ }
- @
- @ public pure model static \bigint pow52(int p5, int p2) {
- @ ghost \bigint v = 1;
- @ for (int i = 0; i < p5; i++) v *= 5;
- @ return v << p2;
- @ }
- @
- @ public pure model static \bigint pow10(int p10) {
- @ return pow52(p10, p10);
- @ }
- @*/
-
- static final int[] SMALL_5_POW = {
- 1,
- 5,
- 5 * 5,
- 5 * 5 * 5,
- 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
- };
-
- static final long[] LONG_5_POW = {
- 1L,
- 5L,
- 5L * 5,
- 5L * 5 * 5,
- 5L * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- };
-
- // Maximum size of cache of powers of 5 as FDBigIntegers.
- private static final int MAX_FIVE_POW = 340;
-
- // Cache of big powers of 5 as FDBigIntegers.
- private static final FDBigInteger POW_5_CACHE[];
-
- // Initialize FDBigInteger cache of powers of 5.
- static {
- POW_5_CACHE = new FDBigInteger[MAX_FIVE_POW];
- int i = 0;
- while (i < SMALL_5_POW.length) {
- FDBigInteger pow5 = new FDBigInteger(new int[]{SMALL_5_POW[i]}, 0);
- pow5.makeImmutable();
- POW_5_CACHE[i] = pow5;
- i++;
- }
- FDBigInteger prev = POW_5_CACHE[i - 1];
- while (i < MAX_FIVE_POW) {
- POW_5_CACHE[i] = prev = prev.mult(5);
- prev.makeImmutable();
- i++;
- }
- }
-
- // Zero as an FDBigInteger.
- public static final FDBigInteger ZERO = new FDBigInteger(new int[0], 0);
-
- // Ensure ZERO is immutable.
- static {
- ZERO.makeImmutable();
- }
-
- // Constant for casting an int to a long via bitwise AND.
- private static final long LONG_MASK = 0xffffffffL;
-
- //@ spec_public non_null;
- private int data[]; // value: data[0] is least significant
- //@ spec_public;
- private int offset; // number of least significant zero padding ints
- //@ spec_public;
- private int nWords; // data[nWords-1]!=0, all values above are zero
- // if nWords==0 -> this FDBigInteger is zero
- //@ spec_public;
- private boolean isImmutable = false;
-
- /*@
- @ public invariant 0 <= nWords && nWords <= data.length && offset >= 0;
- @ public invariant nWords == 0 ==> offset == 0;
- @ public invariant nWords > 0 ==> data[nWords - 1] != 0;
- @ public invariant (\forall int i; nWords <= i && i < data.length; data[i] == 0);
- @ public pure model \bigint value() {
- @ return AP(data, nWords) << (offset*32);
- @ }
- @*/
-
- /**
- * Constructs an <code>FDBigInteger</code> from data and padding. The
- * <code>data</code> parameter has the least significant <code>int</code> at
- * the zeroth index. The <code>offset</code> parameter gives the number of
- * zero <code>int</code>s to be inferred below the least significant element
- * of <code>data</code>.
- *
- * @param data An array containing all non-zero <code>int</code>s of the value.
- * @param offset An offset indicating the number of zero <code>int</code>s to pad
- * below the least significant element of <code>data</code>.
- */
- /*@
- @ requires data != null && offset >= 0;
- @ ensures this.value() == \old(AP(data, data.length) << (offset*32));
- @ ensures this.data == \old(data);
- @*/
- private FDBigInteger(int[] data, int offset) {
- this.data = data;
- this.offset = offset;
- this.nWords = data.length;
- trimLeadingZeros();
- }
-
- /**
- * Constructs an <code>FDBigInteger</code> from a starting value and some
- * decimal digits.
- *
- * @param lValue The starting value.
- * @param digits The decimal digits.
- * @param kDigits The initial index into <code>digits</code>.
- * @param nDigits The final index into <code>digits</code>.
- */
- /*@
- @ requires digits != null;
- @ requires 0 <= kDigits && kDigits <= nDigits && nDigits <= digits.length;
- @ requires (\forall int i; 0 <= i && i < nDigits; '0' <= digits[i] && digits[i] <= '9');
- @ ensures this.value() == \old(lValue * pow10(nDigits - kDigits) + (\sum int i; kDigits <= i && i < nDigits; (digits[i] - '0') * pow10(nDigits - i - 1)));
- @*/
- public FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits) {
- int n = Math.max((nDigits + 8) / 9, 2); // estimate size needed.
- data = new int[n]; // allocate enough space
- data[0] = (int) lValue; // starting value
- data[1] = (int) (lValue >>> 32);
- offset = 0;
- nWords = 2;
- int i = kDigits;
- int limit = nDigits - 5; // slurp digits 5 at a time.
- int v;
- while (i < limit) {
- int ilim = i + 5;
- v = (int) digits[i++] - (int) '0';
- while (i < ilim) {
- v = 10 * v + (int) digits[i++] - (int) '0';
- }
- multAddMe(100000, v); // ... where 100000 is 10^5.
- }
- int factor = 1;
- v = 0;
- while (i < nDigits) {
- v = 10 * v + (int) digits[i++] - (int) '0';
- factor *= 10;
- }
- if (factor != 1) {
- multAddMe(factor, v);
- }
- trimLeadingZeros();
- }
-
- /**
- * Returns an <code>FDBigInteger</code> with the numerical value
- * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
- *
- * @param p5 The exponent of the power-of-five factor.
- * @param p2 The exponent of the power-of-two factor.
- * @return <code>5<sup>p5</sup> * 2<sup>p2</sup></code>
- */
- /*@
- @ requires p5 >= 0 && p2 >= 0;
- @ assignable \nothing;
- @ ensures \result.value() == \old(pow52(p5, p2));
- @*/
- public static FDBigInteger valueOfPow52(int p5, int p2) {
- if (p5 != 0) {
- if (p2 == 0) {
- return big5pow(p5);
- } else if (p5 < SMALL_5_POW.length) {
- int pow5 = SMALL_5_POW[p5];
- int wordcount = p2 >> 5;
- int bitcount = p2 & 0x1f;
- if (bitcount == 0) {
- return new FDBigInteger(new int[]{pow5}, wordcount);
- } else {
- return new FDBigInteger(new int[]{
- pow5 << bitcount,
- pow5 >>> (32 - bitcount)
- }, wordcount);
- }
- } else {
- return big5pow(p5).leftShift(p2);
- }
- } else {
- return valueOfPow2(p2);
- }
- }
-
- /**
- * Returns an <code>FDBigInteger</code> with the numerical value
- * <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>.
- *
- * @param value The constant factor.
- * @param p5 The exponent of the power-of-five factor.
- * @param p2 The exponent of the power-of-two factor.
- * @return <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>
- */
- /*@
- @ requires p5 >= 0 && p2 >= 0;
- @ assignable \nothing;
- @ ensures \result.value() == \old(UNSIGNED(value) * pow52(p5, p2));
- @*/
- public static FDBigInteger valueOfMulPow52(long value, int p5, int p2) {
- assert p5 >= 0 : p5;
- assert p2 >= 0 : p2;
- int v0 = (int) value;
- int v1 = (int) (value >>> 32);
- int wordcount = p2 >> 5;
- int bitcount = p2 & 0x1f;
- if (p5 != 0) {
- if (p5 < SMALL_5_POW.length) {
- long pow5 = SMALL_5_POW[p5] & LONG_MASK;
- long carry = (v0 & LONG_MASK) * pow5;
- v0 = (int) carry;
- carry >>>= 32;
- carry = (v1 & LONG_MASK) * pow5 + carry;
- v1 = (int) carry;
- int v2 = (int) (carry >>> 32);
- if (bitcount == 0) {
- return new FDBigInteger(new int[]{v0, v1, v2}, wordcount);
- } else {
- return new FDBigInteger(new int[]{
- v0 << bitcount,
- (v1 << bitcount) | (v0 >>> (32 - bitcount)),
- (v2 << bitcount) | (v1 >>> (32 - bitcount)),
- v2 >>> (32 - bitcount)
- }, wordcount);
- }
- } else {
- FDBigInteger pow5 = big5pow(p5);
- int[] r;
- if (v1 == 0) {
- r = new int[pow5.nWords + 1 + ((p2 != 0) ? 1 : 0)];
- mult(pow5.data, pow5.nWords, v0, r);
- } else {
- r = new int[pow5.nWords + 2 + ((p2 != 0) ? 1 : 0)];
- mult(pow5.data, pow5.nWords, v0, v1, r);
- }
- return (new FDBigInteger(r, pow5.offset)).leftShift(p2);
- }
- } else if (p2 != 0) {
- if (bitcount == 0) {
- return new FDBigInteger(new int[]{v0, v1}, wordcount);
- } else {
- return new FDBigInteger(new int[]{
- v0 << bitcount,
- (v1 << bitcount) | (v0 >>> (32 - bitcount)),
- v1 >>> (32 - bitcount)
- }, wordcount);
- }
- }
- return new FDBigInteger(new int[]{v0, v1}, 0);
- }
-
- /**
- * Returns an <code>FDBigInteger</code> with the numerical value
- * <code>2<sup>p2</sup></code>.
- *
- * @param p2 The exponent of 2.
- * @return <code>2<sup>p2</sup></code>
- */
- /*@
- @ requires p2 >= 0;
- @ assignable \nothing;
- @ ensures \result.value() == pow52(0, p2);
- @*/
- private static FDBigInteger valueOfPow2(int p2) {
- int wordcount = p2 >> 5;
- int bitcount = p2 & 0x1f;
- return new FDBigInteger(new int[]{1 << bitcount}, wordcount);
- }
-
- /**
- * Removes all leading zeros from this <code>FDBigInteger</code> adjusting
- * the offset and number of non-zero leading words accordingly.
- */
- /*@
- @ requires data != null;
- @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
- @ requires nWords == 0 ==> offset == 0;
- @ ensures nWords == 0 ==> offset == 0;
- @ ensures nWords > 0 ==> data[nWords - 1] != 0;
- @*/
- private /*@ helper @*/ void trimLeadingZeros() {
- int i = nWords;
- if (i > 0 && (data[--i] == 0)) {
- //for (; i > 0 && data[i - 1] == 0; i--) ;
- while(i > 0 && data[i - 1] == 0) {
- i--;
- }
- this.nWords = i;
- if (i == 0) { // all words are zero
- this.offset = 0;
- }
- }
- }
-
- /**
- * Retrieves the normalization bias of the <code>FDBigIntger</code>. The
- * normalization bias is a left shift such that after it the highest word
- * of the value will have the 4 highest bits equal to zero:
- * {@code (highestWord & 0xf0000000) == 0}, but the next bit should be 1
- * {@code (highestWord & 0x08000000) != 0}.
- *
- * @return The normalization bias.
- */
- /*@
- @ requires this.value() > 0;
- @*/
- public /*@ pure @*/ int getNormalizationBias() {
- if (nWords == 0) {
- throw new IllegalArgumentException("Zero value cannot be normalized");
- }
- int zeros = Integer.numberOfLeadingZeros(data[nWords - 1]);
- return (zeros < 4) ? 28 + zeros : zeros - 4;
- }
-
- // TODO: Why is anticount param needed if it is always 32 - bitcount?
- /**
- * Left shifts the contents of one int array into another.
- *
- * @param src The source array.
- * @param idx The initial index of the source array.
- * @param result The destination array.
- * @param bitcount The left shift.
- * @param anticount The left anti-shift, e.g., <code>32-bitcount</code>.
- * @param prev The prior source value.
- */
- /*@
- @ requires 0 < bitcount && bitcount < 32 && anticount == 32 - bitcount;
- @ requires src.length >= idx && result.length > idx;
- @ assignable result[*];
- @ ensures AP(result, \old(idx + 1)) == \old((AP(src, idx) + UNSIGNED(prev) << (idx*32)) << bitcount);
- @*/
- private static void leftShift(int[] src, int idx, int result[], int bitcount, int anticount, int prev){
- for (; idx > 0; idx--) {
- int v = (prev << bitcount);
- prev = src[idx - 1];
- v |= (prev >>> anticount);
- result[idx] = v;
- }
- int v = prev << bitcount;
- result[0] = v;
- }
-
- /**
- * Shifts this <code>FDBigInteger</code> to the left. The shift is performed
- * in-place unless the <code>FDBigInteger</code> is immutable in which case
- * a new instance of <code>FDBigInteger</code> is returned.
- *
- * @param shift The number of bits to shift left.
- * @return The shifted <code>FDBigInteger</code>.
- */
- /*@
- @ requires this.value() == 0 || shift == 0;
- @ assignable \nothing;
- @ ensures \result == this;
- @
- @ also
- @
- @ requires this.value() > 0 && shift > 0 && this.isImmutable;
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() << shift);
- @
- @ also
- @
- @ requires this.value() > 0 && shift > 0 && this.isImmutable;
- @ assignable \nothing;
- @ ensures \result == this;
- @ ensures \result.value() == \old(this.value() << shift);
- @*/
- public FDBigInteger leftShift(int shift) {
- if (shift == 0 || nWords == 0) {
- return this;
- }
- int wordcount = shift >> 5;
- int bitcount = shift & 0x1f;
- if (this.isImmutable) {
- if (bitcount == 0) {
- return new FDBigInteger(Arrays.copyOf(data, nWords), offset + wordcount);
- } else {
- int anticount = 32 - bitcount;
- int idx = nWords - 1;
- int prev = data[idx];
- int hi = prev >>> anticount;
- int[] result;
- if (hi != 0) {
- result = new int[nWords + 1];
- result[nWords] = hi;
- } else {
- result = new int[nWords];
- }
- leftShift(data,idx,result,bitcount,anticount,prev);
- return new FDBigInteger(result, offset + wordcount);
- }
- } else {
- if (bitcount != 0) {
- int anticount = 32 - bitcount;
- if ((data[0] << bitcount) == 0) {
- int idx = 0;
- int prev = data[idx];
- for (; idx < nWords - 1; idx++) {
- int v = (prev >>> anticount);
- prev = data[idx + 1];
- v |= (prev << bitcount);
- data[idx] = v;
- }
- int v = prev >>> anticount;
- data[idx] = v;
- if(v==0) {
- nWords--;
- }
- offset++;
- } else {
- int idx = nWords - 1;
- int prev = data[idx];
- int hi = prev >>> anticount;
- int[] result = data;
- int[] src = data;
- if (hi != 0) {
- if(nWords == data.length) {
- data = result = new int[nWords + 1];
- }
- result[nWords++] = hi;
- }
- leftShift(src,idx,result,bitcount,anticount,prev);
- }
- }
- offset += wordcount;
- return this;
- }
- }
-
- /**
- * Returns the number of <code>int</code>s this <code>FDBigInteger</code> represents.
- *
- * @return Number of <code>int</code>s required to represent this <code>FDBigInteger</code>.
- */
- /*@
- @ requires this.value() == 0;
- @ ensures \result == 0;
- @
- @ also
- @
- @ requires this.value() > 0;
- @ ensures ((\bigint)1) << (\result - 1) <= this.value() && this.value() <= ((\bigint)1) << \result;
- @*/
- private /*@ pure @*/ int size() {
- return nWords + offset;
- }
-
-
- /**
- * Computes
- * <pre>
- * q = (int)( this / S )
- * this = 10 * ( this mod S )
- * Return q.
- * </pre>
- * This is the iteration step of digit development for output.
- * We assume that S has been normalized, as above, and that
- * "this" has been left-shifted accordingly.
- * Also assumed, of course, is that the result, q, can be expressed
- * as an integer, {@code 0 <= q < 10}.
- *
- * @param S The divisor of this <code>FDBigInteger</code>.
- * @return <code>q = (int)(this / S)</code>.
- */
- /*@
- @ requires !this.isImmutable;
- @ requires this.size() <= S.size();
- @ requires this.data.length + this.offset >= S.size();
- @ requires S.value() >= ((\bigint)1) << (S.size()*32 - 4);
- @ assignable this.nWords, this.offset, this.data, this.data[*];
- @ ensures \result == \old(this.value() / S.value());
- @ ensures this.value() == \old(10 * (this.value() % S.value()));
- @*/
- public int quoRemIteration(FDBigInteger S) throws IllegalArgumentException {
- assert !this.isImmutable : "cannot modify immutable value";
- // ensure that this and S have the same number of
- // digits. If S is properly normalized and q < 10 then
- // this must be so.
- int thSize = this.size();
- int sSize = S.size();
- if (thSize < sSize) {
- // this value is significantly less than S, result of division is zero.
- // just mult this by 10.
- int p = multAndCarryBy10(this.data, this.nWords, this.data);
- if(p!=0) {
- this.data[nWords++] = p;
- } else {
- trimLeadingZeros();
- }
- return 0;
- } else if (thSize > sSize) {
- throw new IllegalArgumentException("disparate values");
- }
- // estimate q the obvious way. We will usually be
- // right. If not, then we're only off by a little and
- // will re-add.
- long q = (this.data[this.nWords - 1] & LONG_MASK) / (S.data[S.nWords - 1] & LONG_MASK);
- long diff = multDiffMe(q, S);
- if (diff != 0L) {
- //@ assert q != 0;
- //@ assert this.offset == \old(Math.min(this.offset, S.offset));
- //@ assert this.offset <= S.offset;
-
- // q is too big.
- // add S back in until this turns +. This should
- // not be very many times!
- long sum = 0L;
- int tStart = S.offset - this.offset;
- //@ assert tStart >= 0;
- int[] sd = S.data;
- int[] td = this.data;
- while (sum == 0L) {
- for (int sIndex = 0, tIndex = tStart; tIndex < this.nWords; sIndex++, tIndex++) {
- sum += (td[tIndex] & LONG_MASK) + (sd[sIndex] & LONG_MASK);
- td[tIndex] = (int) sum;
- sum >>>= 32; // Signed or unsigned, answer is 0 or 1
- }
- //
- // Originally the following line read
- // "if ( sum !=0 && sum != -1 )"
- // but that would be wrong, because of the
- // treatment of the two values as entirely unsigned,
- // it would be impossible for a carry-out to be interpreted
- // as -1 -- it would have to be a single-bit carry-out, or +1.
- //
- assert sum == 0 || sum == 1 : sum; // carry out of division correction
- q -= 1;
- }
- }
- // finally, we can multiply this by 10.
- // it cannot overflow, right, as the high-order word has
- // at least 4 high-order zeros!
- int p = multAndCarryBy10(this.data, this.nWords, this.data);
- assert p == 0 : p; // Carry out of *10
- trimLeadingZeros();
- return (int) q;
- }
-
- /**
- * Multiplies this <code>FDBigInteger</code> by 10. The operation will be
- * performed in place unless the <code>FDBigInteger</code> is immutable in
- * which case a new <code>FDBigInteger</code> will be returned.
- *
- * @return The <code>FDBigInteger</code> multiplied by 10.
- */
- /*@
- @ requires this.value() == 0;
- @ assignable \nothing;
- @ ensures \result == this;
- @
- @ also
- @
- @ requires this.value() > 0 && this.isImmutable;
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() * 10);
- @
- @ also
- @
- @ requires this.value() > 0 && !this.isImmutable;
- @ assignable this.nWords, this.data, this.data[*];
- @ ensures \result == this;
- @ ensures \result.value() == \old(this.value() * 10);
- @*/
- public FDBigInteger multBy10() {
- if (nWords == 0) {
- return this;
- }
- if (isImmutable) {
- int[] res = new int[nWords + 1];
- res[nWords] = multAndCarryBy10(data, nWords, res);
- return new FDBigInteger(res, offset);
- } else {
- int p = multAndCarryBy10(this.data, this.nWords, this.data);
- if (p != 0) {
- if (nWords == data.length) {
- if (data[0] == 0) {
- System.arraycopy(data, 1, data, 0, --nWords);
- offset++;
- } else {
- data = Arrays.copyOf(data, data.length + 1);
- }
- }
- data[nWords++] = p;
- } else {
- trimLeadingZeros();
- }
- return this;
- }
- }
-
- /**
- * Multiplies this <code>FDBigInteger</code> by
- * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>. The operation will be
- * performed in place if possible, otherwise a new <code>FDBigInteger</code>
- * will be returned.
- *
- * @param p5 The exponent of the power-of-five factor.
- * @param p2 The exponent of the power-of-two factor.
- * @return The multiplication result.
- */
- /*@
- @ requires this.value() == 0 || p5 == 0 && p2 == 0;
- @ assignable \nothing;
- @ ensures \result == this;
- @
- @ also
- @
- @ requires this.value() > 0 && (p5 > 0 && p2 >= 0 || p5 == 0 && p2 > 0 && this.isImmutable);
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
- @
- @ also
- @
- @ requires this.value() > 0 && p5 == 0 && p2 > 0 && !this.isImmutable;
- @ assignable this.nWords, this.data, this.data[*];
- @ ensures \result == this;
- @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
- @*/
- public FDBigInteger multByPow52(int p5, int p2) {
- if (this.nWords == 0) {
- return this;
- }
- FDBigInteger res = this;
- if (p5 != 0) {
- int[] r;
- int extraSize = (p2 != 0) ? 1 : 0;
- if (p5 < SMALL_5_POW.length) {
- r = new int[this.nWords + 1 + extraSize];
- mult(this.data, this.nWords, SMALL_5_POW[p5], r);
- res = new FDBigInteger(r, this.offset);
- } else {
- FDBigInteger pow5 = big5pow(p5);
- r = new int[this.nWords + pow5.size() + extraSize];
- mult(this.data, this.nWords, pow5.data, pow5.nWords, r);
- res = new FDBigInteger(r, this.offset + pow5.offset);
- }
- }
- return res.leftShift(p2);
- }
-
- /**
- * Multiplies two big integers represented as int arrays.
- *
- * @param s1 The first array factor.
- * @param s1Len The number of elements of <code>s1</code> to use.
- * @param s2 The second array factor.
- * @param s2Len The number of elements of <code>s2</code> to use.
- * @param dst The product array.
- */
- /*@
- @ requires s1 != dst && s2 != dst;
- @ requires s1.length >= s1Len && s2.length >= s2Len && dst.length >= s1Len + s2Len;
- @ assignable dst[0 .. s1Len + s2Len - 1];
- @ ensures AP(dst, s1Len + s2Len) == \old(AP(s1, s1Len) * AP(s2, s2Len));
- @*/
- private static void mult(int[] s1, int s1Len, int[] s2, int s2Len, int[] dst) {
- for (int i = 0; i < s1Len; i++) {
- long v = s1[i] & LONG_MASK;
- long p = 0L;
- for (int j = 0; j < s2Len; j++) {
- p += (dst[i + j] & LONG_MASK) + v * (s2[j] & LONG_MASK);
- dst[i + j] = (int) p;
- p >>>= 32;
- }
- dst[i + s2Len] = (int) p;
- }
- }
-
- /**
- * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
- * <code>FDBigInteger</code>. Assert that the result is positive.
- * If the subtrahend is immutable, store the result in this(minuend).
- * If this(minuend) is immutable a new <code>FDBigInteger</code> is created.
- *
- * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
- * @return This <code>FDBigInteger</code> less the subtrahend.
- */
- /*@
- @ requires this.isImmutable;
- @ requires this.value() >= subtrahend.value();
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() - subtrahend.value());
- @
- @ also
- @
- @ requires !subtrahend.isImmutable;
- @ requires this.value() >= subtrahend.value();
- @ assignable this.nWords, this.offset, this.data, this.data[*];
- @ ensures \result == this;
- @ ensures \result.value() == \old(this.value() - subtrahend.value());
- @*/
- public FDBigInteger leftInplaceSub(FDBigInteger subtrahend) {
- assert this.size() >= subtrahend.size() : "result should be positive";
- FDBigInteger minuend;
- if (this.isImmutable) {
- minuend = new FDBigInteger(this.data.clone(), this.offset);
- } else {
- minuend = this;
- }
- int offsetDiff = subtrahend.offset - minuend.offset;
- int[] sData = subtrahend.data;
- int[] mData = minuend.data;
- int subLen = subtrahend.nWords;
- int minLen = minuend.nWords;
- if (offsetDiff < 0) {
- // need to expand minuend
- int rLen = minLen - offsetDiff;
- if (rLen < mData.length) {
- System.arraycopy(mData, 0, mData, -offsetDiff, minLen);
- Arrays.fill(mData, 0, -offsetDiff, 0);
- } else {
- int[] r = new int[rLen];
- System.arraycopy(mData, 0, r, -offsetDiff, minLen);
- minuend.data = mData = r;
- }
- minuend.offset = subtrahend.offset;
- minuend.nWords = minLen = rLen;
- offsetDiff = 0;
- }
- long borrow = 0L;
- int mIndex = offsetDiff;
- for (int sIndex = 0; sIndex < subLen && mIndex < minLen; sIndex++, mIndex++) {
- long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
- mData[mIndex] = (int) diff;
- borrow = diff >> 32; // signed shift
- }
- for (; borrow != 0 && mIndex < minLen; mIndex++) {
- long diff = (mData[mIndex] & LONG_MASK) + borrow;
- mData[mIndex] = (int) diff;
- borrow = diff >> 32; // signed shift
- }
- assert borrow == 0L : borrow; // borrow out of subtract,
- // result should be positive
- minuend.trimLeadingZeros();
- return minuend;
- }
-
- /**
- * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
- * <code>FDBigInteger</code>. Assert that the result is positive.
- * If the this(minuend) is immutable, store the result in subtrahend.
- * If subtrahend is immutable a new <code>FDBigInteger</code> is created.
- *
- * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
- * @return This <code>FDBigInteger</code> less the subtrahend.
- */
- /*@
- @ requires subtrahend.isImmutable;
- @ requires this.value() >= subtrahend.value();
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() - subtrahend.value());
- @
- @ also
- @
- @ requires !subtrahend.isImmutable;
- @ requires this.value() >= subtrahend.value();
- @ assignable subtrahend.nWords, subtrahend.offset, subtrahend.data, subtrahend.data[*];
- @ ensures \result == subtrahend;
- @ ensures \result.value() == \old(this.value() - subtrahend.value());
- @*/
- public FDBigInteger rightInplaceSub(FDBigInteger subtrahend) {
- assert this.size() >= subtrahend.size() : "result should be positive";
- FDBigInteger minuend = this;
- if (subtrahend.isImmutable) {
- subtrahend = new FDBigInteger(subtrahend.data.clone(), subtrahend.offset);
- }
- int offsetDiff = minuend.offset - subtrahend.offset;
- int[] sData = subtrahend.data;
- int[] mData = minuend.data;
- int subLen = subtrahend.nWords;
- int minLen = minuend.nWords;
- if (offsetDiff < 0) {
- int rLen = minLen;
- if (rLen < sData.length) {
- System.arraycopy(sData, 0, sData, -offsetDiff, subLen);
- Arrays.fill(sData, 0, -offsetDiff, 0);
- } else {
- int[] r = new int[rLen];
- System.arraycopy(sData, 0, r, -offsetDiff, subLen);
- subtrahend.data = sData = r;
- }
- subtrahend.offset = minuend.offset;
- subLen -= offsetDiff;
- offsetDiff = 0;
- } else {
- int rLen = minLen + offsetDiff;
- if (rLen >= sData.length) {
- subtrahend.data = sData = Arrays.copyOf(sData, rLen);
- }
- }
- //@ assert minuend == this && minuend.value() == \old(this.value());
- //@ assert mData == minuend.data && minLen == minuend.nWords;
- //@ assert subtrahend.offset + subtrahend.data.length >= minuend.size();
- //@ assert sData == subtrahend.data;
- //@ assert AP(subtrahend.data, subtrahend.data.length) << subtrahend.offset == \old(subtrahend.value());
- //@ assert subtrahend.offset == Math.min(\old(this.offset), minuend.offset);
- //@ assert offsetDiff == minuend.offset - subtrahend.offset;
- //@ assert 0 <= offsetDiff && offsetDiff + minLen <= sData.length;
- int sIndex = 0;
- long borrow = 0L;
- for (; sIndex < offsetDiff; sIndex++) {
- long diff = 0L - (sData[sIndex] & LONG_MASK) + borrow;
- sData[sIndex] = (int) diff;
- borrow = diff >> 32; // signed shift
- }
- //@ assert sIndex == offsetDiff;
- for (int mIndex = 0; mIndex < minLen; sIndex++, mIndex++) {
- //@ assert sIndex == offsetDiff + mIndex;
- long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
- sData[sIndex] = (int) diff;
- borrow = diff >> 32; // signed shift
- }
- assert borrow == 0L : borrow; // borrow out of subtract,
- // result should be positive
- subtrahend.nWords = sIndex;
- subtrahend.trimLeadingZeros();
- return subtrahend;
-
- }
-
- /**
- * Determines whether all elements of an array are zero for all indices less
- * than a given index.
- *
- * @param a The array to be examined.
- * @param from The index strictly below which elements are to be examined.
- * @return Zero if all elements in range are zero, 1 otherwise.
- */
- /*@
- @ requires 0 <= from && from <= a.length;
- @ ensures \result == (AP(a, from) == 0 ? 0 : 1);
- @*/
- private /*@ pure @*/ static int checkZeroTail(int[] a, int from) {
- while (from > 0) {
- if (a[--from] != 0) {
- return 1;
- }
- }
- return 0;
- }
-
- /**
- * Compares the parameter with this <code>FDBigInteger</code>. Returns an
- * integer accordingly as:
- * <pre>{@code
- * > 0: this > other
- * 0: this == other
- * < 0: this < other
- * }</pre>
- *
- * @param other The <code>FDBigInteger</code> to compare.
- * @return A negative value, zero, or a positive value according to the
- * result of the comparison.
- */
- /*@
- @ ensures \result == (this.value() < other.value() ? -1 : this.value() > other.value() ? +1 : 0);
- @*/
- public /*@ pure @*/ int cmp(FDBigInteger other) {
- int aSize = nWords + offset;
- int bSize = other.nWords + other.offset;
- if (aSize > bSize) {
- return 1;
- } else if (aSize < bSize) {
- return -1;
- }
- int aLen = nWords;
- int bLen = other.nWords;
- while (aLen > 0 && bLen > 0) {
- int a = data[--aLen];
- int b = other.data[--bLen];
- if (a != b) {
- return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
- }
- }
- if (aLen > 0) {
- return checkZeroTail(data, aLen);
- }
- if (bLen > 0) {
- return -checkZeroTail(other.data, bLen);
- }
- return 0;
- }
-
- /**
- * Compares this <code>FDBigInteger</code> with
- * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
- * Returns an integer accordingly as:
- * <pre>{@code
- * > 0: this > other
- * 0: this == other
- * < 0: this < other
- * }</pre>
- * @param p5 The exponent of the power-of-five factor.
- * @param p2 The exponent of the power-of-two factor.
- * @return A negative value, zero, or a positive value according to the
- * result of the comparison.
- */
- /*@
- @ requires p5 >= 0 && p2 >= 0;
- @ ensures \result == (this.value() < pow52(p5, p2) ? -1 : this.value() > pow52(p5, p2) ? +1 : 0);
- @*/
- public /*@ pure @*/ int cmpPow52(int p5, int p2) {
- if (p5 == 0) {
- int wordcount = p2 >> 5;
- int bitcount = p2 & 0x1f;
- int size = this.nWords + this.offset;
- if (size > wordcount + 1) {
- return 1;
- } else if (size < wordcount + 1) {
- return -1;
- }
- int a = this.data[this.nWords -1];
- int b = 1 << bitcount;
- if (a != b) {
- return ( (a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
- }
- return checkZeroTail(this.data, this.nWords - 1);
- }
- return this.cmp(big5pow(p5).leftShift(p2));
- }
-
- /**
- * Compares this <code>FDBigInteger</code> with <code>x + y</code>. Returns a
- * value according to the comparison as:
- * <pre>{@code
- * -1: this < x + y
- * 0: this == x + y
- * 1: this > x + y
- * }</pre>
- * @param x The first addend of the sum to compare.
- * @param y The second addend of the sum to compare.
- * @return -1, 0, or 1 according to the result of the comparison.
- */
- /*@
- @ ensures \result == (this.value() < x.value() + y.value() ? -1 : this.value() > x.value() + y.value() ? +1 : 0);
- @*/
- public /*@ pure @*/ int addAndCmp(FDBigInteger x, FDBigInteger y) {
- FDBigInteger big;
- FDBigInteger small;
- int xSize = x.size();
- int ySize = y.size();
- int bSize;
- int sSize;
- if (xSize >= ySize) {
- big = x;
- small = y;
- bSize = xSize;
- sSize = ySize;
- } else {
- big = y;
- small = x;
- bSize = ySize;
- sSize = xSize;
- }
- int thSize = this.size();
- if (bSize == 0) {
- return thSize == 0 ? 0 : 1;
- }
- if (sSize == 0) {
- return this.cmp(big);
- }
- if (bSize > thSize) {
- return -1;
- }
- if (bSize + 1 < thSize) {
- return 1;
- }
- long top = (big.data[big.nWords - 1] & LONG_MASK);
- if (sSize == bSize) {
- top += (small.data[small.nWords - 1] & LONG_MASK);
- }
- if ((top >>> 32) == 0) {
- if (((top + 1) >>> 32) == 0) {
- // good case - no carry extension
- if (bSize < thSize) {
- return 1;
- }
- // here sum.nWords == this.nWords
- long v = (this.data[this.nWords - 1] & LONG_MASK);
- if (v < top) {
- return -1;
- }
- if (v > top + 1) {
- return 1;
- }
- }
- } else { // (top>>>32)!=0 guaranteed carry extension
- if (bSize + 1 > thSize) {
- return -1;
- }
- // here sum.nWords == this.nWords
- top >>>= 32;
- long v = (this.data[this.nWords - 1] & LONG_MASK);
- if (v < top) {
- return -1;
- }
- if (v > top + 1) {
- return 1;
- }
- }
- return this.cmp(big.add(small));
- }
-
- /**
- * Makes this <code>FDBigInteger</code> immutable.
- */
- /*@
- @ assignable this.isImmutable;
- @ ensures this.isImmutable;
- @*/
- public void makeImmutable() {
- this.isImmutable = true;
- }
-
- /**
- * Multiplies this <code>FDBigInteger</code> by an integer.
- *
- * @param i The factor by which to multiply this <code>FDBigInteger</code>.
- * @return This <code>FDBigInteger</code> multiplied by an integer.
- */
- /*@
- @ requires this.value() == 0;
- @ assignable \nothing;
- @ ensures \result == this;
- @
- @ also
- @
- @ requires this.value() != 0;
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() * UNSIGNED(i));
- @*/
- private FDBigInteger mult(int i) {
- if (this.nWords == 0) {
- return this;
- }
- int[] r = new int[nWords + 1];
- mult(data, nWords, i, r);
- return new FDBigInteger(r, offset);
- }
-
- /**
- * Multiplies this <code>FDBigInteger</code> by another <code>FDBigInteger</code>.
- *
- * @param other The <code>FDBigInteger</code> factor by which to multiply.
- * @return The product of this and the parameter <code>FDBigInteger</code>s.
- */
- /*@
- @ requires this.value() == 0;
- @ assignable \nothing;
- @ ensures \result == this;
- @
- @ also
- @
- @ requires this.value() != 0 && other.value() == 0;
- @ assignable \nothing;
- @ ensures \result == other;
- @
- @ also
- @
- @ requires this.value() != 0 && other.value() != 0;
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() * other.value());
- @*/
- private FDBigInteger mult(FDBigInteger other) {
- if (this.nWords == 0) {
- return this;
- }
- if (this.size() == 1) {
- return other.mult(data[0]);
- }
- if (other.nWords == 0) {
- return other;
- }
- if (other.size() == 1) {
- return this.mult(other.data[0]);
- }
- int[] r = new int[nWords + other.nWords];
- mult(this.data, this.nWords, other.data, other.nWords, r);
- return new FDBigInteger(r, this.offset + other.offset);
- }
-
- /**
- * Adds another <code>FDBigInteger</code> to this <code>FDBigInteger</code>.
- *
- * @param other The <code>FDBigInteger</code> to add.
- * @return The sum of the <code>FDBigInteger</code>s.
- */
- /*@
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() + other.value());
- @*/
- private FDBigInteger add(FDBigInteger other) {
- FDBigInteger big, small;
- int bigLen, smallLen;
- int tSize = this.size();
- int oSize = other.size();
- if (tSize >= oSize) {
- big = this;
- bigLen = tSize;
- small = other;
- smallLen = oSize;
- } else {
- big = other;
- bigLen = oSize;
- small = this;
- smallLen = tSize;
- }
- int[] r = new int[bigLen + 1];
- int i = 0;
- long carry = 0L;
- for (; i < smallLen; i++) {
- carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) )
- + ((i < small.offset ? 0L : (small.data[i - small.offset] & LONG_MASK)));
- r[i] = (int) carry;
- carry >>= 32; // signed shift.
- }
- for (; i < bigLen; i++) {
- carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) );
- r[i] = (int) carry;
- carry >>= 32; // signed shift.
- }
- r[bigLen] = (int) carry;
- return new FDBigInteger(r, 0);
- }
-
-
- /**
- * Multiplies a <code>FDBigInteger</code> by an int and adds another int. The
- * result is computed in place. This method is intended only to be invoked
- * from
- * <code>
- * FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits)
- * </code>.
- *
- * @param iv The factor by which to multiply this <code>FDBigInteger</code>.
- * @param addend The value to add to the product of this
- * <code>FDBigInteger</code> and <code>iv</code>.
- */
- /*@
- @ requires this.value()*UNSIGNED(iv) + UNSIGNED(addend) < ((\bigint)1) << ((this.data.length + this.offset)*32);
- @ assignable this.data[*];
- @ ensures this.value() == \old(this.value()*UNSIGNED(iv) + UNSIGNED(addend));
- @*/
- private /*@ helper @*/ void multAddMe(int iv, int addend) {
- long v = iv & LONG_MASK;
- // unroll 0th iteration, doing addition.
- long p = v * (data[0] & LONG_MASK) + (addend & LONG_MASK);
- data[0] = (int) p;
- p >>>= 32;
- for (int i = 1; i < nWords; i++) {
- p += v * (data[i] & LONG_MASK);
- data[i] = (int) p;
- p >>>= 32;
- }
- if (p != 0L) {
- data[nWords++] = (int) p; // will fail noisily if illegal!
- }
- }
-
- //
- // original doc:
- //
- // do this -=q*S
- // returns borrow
- //
- /**
- * Multiplies the parameters and subtracts them from this
- * <code>FDBigInteger</code>.
- *
- * @param q The integer parameter.
- * @param S The <code>FDBigInteger</code> parameter.
- * @return <code>this - q*S</code>.
- */
- /*@
- @ ensures nWords == 0 ==> offset == 0;
- @ ensures nWords > 0 ==> data[nWords - 1] != 0;
- @*/
- /*@
- @ requires 0 < q && q <= (1L << 31);
- @ requires data != null;
- @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
- @ requires !this.isImmutable;
- @ requires this.size() == S.size();
- @ requires this != S;
- @ assignable this.nWords, this.offset, this.data, this.data[*];
- @ ensures -q <= \result && \result <= 0;
- @ ensures this.size() == \old(this.size());
- @ ensures this.value() + (\result << (this.size()*32)) == \old(this.value() - q*S.value());
- @ ensures this.offset == \old(Math.min(this.offset, S.offset));
- @ ensures \old(this.offset <= S.offset) ==> this.nWords == \old(this.nWords);
- @ ensures \old(this.offset <= S.offset) ==> this.offset == \old(this.offset);
- @ ensures \old(this.offset <= S.offset) ==> this.data == \old(this.data);
- @
- @ also
- @
- @ requires q == 0;
- @ assignable \nothing;
- @ ensures \result == 0;
- @*/
- private /*@ helper @*/ long multDiffMe(long q, FDBigInteger S) {
- long diff = 0L;
- if (q != 0) {
- int deltaSize = S.offset - this.offset;
- if (deltaSize >= 0) {
- int[] sd = S.data;
- int[] td = this.data;
- for (int sIndex = 0, tIndex = deltaSize; sIndex < S.nWords; sIndex++, tIndex++) {
- diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
- td[tIndex] = (int) diff;
- diff >>= 32; // N.B. SIGNED shift.
- }
- } else {
- deltaSize = -deltaSize;
- int[] rd = new int[nWords + deltaSize];
- int sIndex = 0;
- int rIndex = 0;
- int[] sd = S.data;
- for (; rIndex < deltaSize && sIndex < S.nWords; sIndex++, rIndex++) {
- diff -= q * (sd[sIndex] & LONG_MASK);
- rd[rIndex] = (int) diff;
- diff >>= 32; // N.B. SIGNED shift.
- }
- int tIndex = 0;
- int[] td = this.data;
- for (; sIndex < S.nWords; sIndex++, tIndex++, rIndex++) {
- diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
- rd[rIndex] = (int) diff;
- diff >>= 32; // N.B. SIGNED shift.
- }
- this.nWords += deltaSize;
- this.offset -= deltaSize;
- this.data = rd;
- }
- }
- return diff;
- }
-
-
- /**
- * Multiplies by 10 a big integer represented as an array. The final carry
- * is returned.
- *
- * @param src The array representation of the big integer.
- * @param srcLen The number of elements of <code>src</code> to use.
- * @param dst The product array.
- * @return The final carry of the multiplication.
- */
- /*@
- @ requires src.length >= srcLen && dst.length >= srcLen;
- @ assignable dst[0 .. srcLen - 1];
- @ ensures 0 <= \result && \result < 10;
- @ ensures AP(dst, srcLen) + (\result << (srcLen*32)) == \old(AP(src, srcLen) * 10);
- @*/
- private static int multAndCarryBy10(int[] src, int srcLen, int[] dst) {
- long carry = 0;
- for (int i = 0; i < srcLen; i++) {
- long product = (src[i] & LONG_MASK) * 10L + carry;
- dst[i] = (int) product;
- carry = product >>> 32;
- }
- return (int) carry;
- }
-
- /**
- * Multiplies by a constant value a big integer represented as an array.
- * The constant factor is an <code>int</code>.
- *
- * @param src The array representation of the big integer.
- * @param srcLen The number of elements of <code>src</code> to use.
- * @param value The constant factor by which to multiply.
- * @param dst The product array.
- */
- /*@
- @ requires src.length >= srcLen && dst.length >= srcLen + 1;
- @ assignable dst[0 .. srcLen];
- @ ensures AP(dst, srcLen + 1) == \old(AP(src, srcLen) * UNSIGNED(value));
- @*/
- private static void mult(int[] src, int srcLen, int value, int[] dst) {
- long val = value & LONG_MASK;
- long carry = 0;
- for (int i = 0; i < srcLen; i++) {
- long product = (src[i] & LONG_MASK) * val + carry;
- dst[i] = (int) product;
- carry = product >>> 32;
- }
- dst[srcLen] = (int) carry;
- }
-
- /**
- * Multiplies by a constant value a big integer represented as an array.
- * The constant factor is a long represent as two <code>int</code>s.
- *
- * @param src The array representation of the big integer.
- * @param srcLen The number of elements of <code>src</code> to use.
- * @param v0 The lower 32 bits of the long factor.
- * @param v1 The upper 32 bits of the long factor.
- * @param dst The product array.
- */
- /*@
- @ requires src != dst;
- @ requires src.length >= srcLen && dst.length >= srcLen + 2;
- @ assignable dst[0 .. srcLen + 1];
- @ ensures AP(dst, srcLen + 2) == \old(AP(src, srcLen) * (UNSIGNED(v0) + (UNSIGNED(v1) << 32)));
- @*/
- private static void mult(int[] src, int srcLen, int v0, int v1, int[] dst) {
- long v = v0 & LONG_MASK;
- long carry = 0;
- for (int j = 0; j < srcLen; j++) {
- long product = v * (src[j] & LONG_MASK) + carry;
- dst[j] = (int) product;
- carry = product >>> 32;
- }
- dst[srcLen] = (int) carry;
- v = v1 & LONG_MASK;
- carry = 0;
- for (int j = 0; j < srcLen; j++) {
- long product = (dst[j + 1] & LONG_MASK) + v * (src[j] & LONG_MASK) + carry;
- dst[j + 1] = (int) product;
- carry = product >>> 32;
- }
- dst[srcLen + 1] = (int) carry;
- }
-
- // Fails assertion for negative exponent.
- /**
- * Computes <code>5</code> raised to a given power.
- *
- * @param p The exponent of 5.
- * @return <code>5<sup>p</sup></code>.
- */
- private static FDBigInteger big5pow(int p) {
- assert p >= 0 : p; // negative power of 5
- if (p < MAX_FIVE_POW) {
- return POW_5_CACHE[p];
- }
- return big5powRec(p);
- }
-
- // slow path
- /**
- * Computes <code>5</code> raised to a given power.
- *
- * @param p The exponent of 5.
- * @return <code>5<sup>p</sup></code>.
- */
- private static FDBigInteger big5powRec(int p) {
- if (p < MAX_FIVE_POW) {
- return POW_5_CACHE[p];
- }
- // construct the value.
- // recursively.
- int q, r;
- // in order to compute 5^p,
- // compute its square root, 5^(p/2) and square.
- // or, let q = p / 2, r = p -q, then
- // 5^p = 5^(q+r) = 5^q * 5^r
- q = p >> 1;
- r = p - q;
- FDBigInteger bigq = big5powRec(q);
- if (r < SMALL_5_POW.length) {
- return bigq.mult(SMALL_5_POW[r]);
- } else {
- return bigq.mult(big5powRec(r));
- }
- }
-
- // for debugging ...
- /**
- * Converts this <code>FDBigInteger</code> to a hexadecimal string.
- *
- * @return The hexadecimal string representation.
- */
- public String toHexString(){
- if(nWords ==0) {
- return "0";
- }
- StringBuilder sb = new StringBuilder((nWords +offset)*8);
- for(int i= nWords -1; i>=0; i--) {
- String subStr = Integer.toHexString(data[i]);
- for(int j = subStr.length(); j<8; j++) {
- sb.append('0');
- }
- sb.append(subStr);
- }
- for(int i=offset; i>0; i--) {
- sb.append("00000000");
- }
- return sb.toString();
- }
-
- // for debugging ...
- /**
- * Converts this <code>FDBigInteger</code> to a <code>BigInteger</code>.
- *
- * @return The <code>BigInteger</code> representation.
- */
- public BigInteger toBigInteger() {
- byte[] magnitude = new byte[nWords * 4 + 1];
- for (int i = 0; i < nWords; i++) {
- int w = data[i];
- magnitude[magnitude.length - 4 * i - 1] = (byte) w;
- magnitude[magnitude.length - 4 * i - 2] = (byte) (w >> 8);
- magnitude[magnitude.length - 4 * i - 3] = (byte) (w >> 16);
- magnitude[magnitude.length - 4 * i - 4] = (byte) (w >> 24);
- }
- return new BigInteger(magnitude).shiftLeft(offset * 32);
- }
-
- // for debugging ...
- /**
- * Converts this <code>FDBigInteger</code> to a string.
- *
- * @return The string representation.
- */
- @Override
- public String toString(){
- return toBigInteger().toString();
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/FloatConsts.java Tue Dec 22 11:07:17 2015 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-/**
- * This class contains additional constants documenting limits of the
- * <code>float</code> type.
- *
- * @author Joseph D. Darcy
- */
-
-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.
- */
- 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)));
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/FloatingDecimal.java Tue Dec 22 11:07:17 2015 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2552 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.util.Arrays;
-import java.util.regex.*;
-
-/**
- * A class for converting between ASCII and decimal representations of a single
- * or double precision floating point number. Most conversions are provided via
- * static convenience methods, although a <code>BinaryToASCIIConverter</code>
- * instance may be obtained and reused.
- */
-public class FloatingDecimal{
- //
- // Constants of the implementation;
- // most are IEEE-754 related.
- // (There are more really boring constants at the end.)
- //
- static final int EXP_SHIFT = DoubleConsts.SIGNIFICAND_WIDTH - 1;
- static final long FRACT_HOB = ( 1L<<EXP_SHIFT ); // assumed High-Order bit
- static final long EXP_ONE = ((long)DoubleConsts.EXP_BIAS)<<EXP_SHIFT; // exponent of 1.0
- static final int MAX_SMALL_BIN_EXP = 62;
- static final int MIN_SMALL_BIN_EXP = -( 63 / 3 );
- static final int MAX_DECIMAL_DIGITS = 15;
- static final int MAX_DECIMAL_EXPONENT = 308;
- static final int MIN_DECIMAL_EXPONENT = -324;
- static final int BIG_DECIMAL_EXPONENT = 324; // i.e. abs(MIN_DECIMAL_EXPONENT)
- static final int MAX_NDIGITS = 1100;
-
- static final int SINGLE_EXP_SHIFT = FloatConsts.SIGNIFICAND_WIDTH - 1;
- static final int SINGLE_FRACT_HOB = 1<<SINGLE_EXP_SHIFT;
- static final int SINGLE_MAX_DECIMAL_DIGITS = 7;
- static final int SINGLE_MAX_DECIMAL_EXPONENT = 38;
- static final int SINGLE_MIN_DECIMAL_EXPONENT = -45;
- static final int SINGLE_MAX_NDIGITS = 200;
-
- static final int INT_DECIMAL_DIGITS = 9;
-
- /**
- * Converts a double precision floating point value to a <code>String</code>.
- *
- * @param d The double precision value.
- * @return The value converted to a <code>String</code>.
- */
- public static String toJavaFormatString(double d) {
- return getBinaryToASCIIConverter(d).toJavaFormatString();
- }
-
- /**
- * Converts a single precision floating point value to a <code>String</code>.
- *
- * @param f The single precision value.
- * @return The value converted to a <code>String</code>.
- */
- public static String toJavaFormatString(float f) {
- return getBinaryToASCIIConverter(f).toJavaFormatString();
- }
-
- /**
- * Appends a double precision floating point value to an <code>Appendable</code>.
- * @param d The double precision value.
- * @param buf The <code>Appendable</code> with the value appended.
- */
- public static void appendTo(double d, Appendable buf) {
- getBinaryToASCIIConverter(d).appendTo(buf);
- }
-
- /**
- * Appends a single precision floating point value to an <code>Appendable</code>.
- * @param f The single precision value.
- * @param buf The <code>Appendable</code> with the value appended.
- */
- public static void appendTo(float f, Appendable buf) {
- getBinaryToASCIIConverter(f).appendTo(buf);
- }
-
- /**
- * Converts a <code>String</code> to a double precision floating point value.
- *
- * @param s The <code>String</code> to convert.
- * @return The double precision value.
- * @throws NumberFormatException If the <code>String</code> does not
- * represent a properly formatted double precision value.
- */
- public static double parseDouble(String s) throws NumberFormatException {
- return readJavaFormatString(s).doubleValue();
- }
-
- /**
- * Converts a <code>String</code> to a single precision floating point value.
- *
- * @param s The <code>String</code> to convert.
- * @return The single precision value.
- * @throws NumberFormatException If the <code>String</code> does not
- * represent a properly formatted single precision value.
- */
- public static float parseFloat(String s) throws NumberFormatException {
- return readJavaFormatString(s).floatValue();
- }
-
- /**
- * A converter which can process single or double precision floating point
- * values into an ASCII <code>String</code> representation.
- */
- public interface BinaryToASCIIConverter {
- /**
- * Converts a floating point value into an ASCII <code>String</code>.
- * @return The value converted to a <code>String</code>.
- */
- public String toJavaFormatString();
-
- /**
- * Appends a floating point value to an <code>Appendable</code>.
- * @param buf The <code>Appendable</code> to receive the value.
- */
- public void appendTo(Appendable buf);
-
- /**
- * Retrieves the decimal exponent most closely corresponding to this value.
- * @return The decimal exponent.
- */
- public int getDecimalExponent();
-
- /**
- * Retrieves the value as an array of digits.
- * @param digits The digit array.
- * @return The number of valid digits copied into the array.
- */
- public int getDigits(char[] digits);
-
- /**
- * Indicates the sign of the value.
- * @return {@code value < 0.0}.
- */
- public boolean isNegative();
-
- /**
- * Indicates whether the value is either infinite or not a number.
- *
- * @return <code>true</code> if and only if the value is <code>NaN</code>
- * or infinite.
- */
- public boolean isExceptional();
-
- /**
- * Indicates whether the value was rounded up during the binary to ASCII
- * conversion.
- *
- * @return <code>true</code> if and only if the value was rounded up.
- */
- public boolean digitsRoundedUp();
-
- /**
- * Indicates whether the binary to ASCII conversion was exact.
- *
- * @return <code>true</code> if any only if the conversion was exact.
- */
- public boolean decimalDigitsExact();
- }
-
- /**
- * A <code>BinaryToASCIIConverter</code> which represents <code>NaN</code>
- * and infinite values.
- */
- private static class ExceptionalBinaryToASCIIBuffer implements BinaryToASCIIConverter {
- private final String image;
- private boolean isNegative;
-
- public ExceptionalBinaryToASCIIBuffer(String image, boolean isNegative) {
- this.image = image;
- this.isNegative = isNegative;
- }
-
- @Override
- public String toJavaFormatString() {
- return image;
- }
-
- @Override
- public void appendTo(Appendable buf) {
- if (buf instanceof StringBuilder) {
- ((StringBuilder) buf).append(image);
- } else if (buf instanceof StringBuffer) {
- ((StringBuffer) buf).append(image);
- } else {
- assert false;
- }
- }
-
- @Override
- public int getDecimalExponent() {
- throw new IllegalArgumentException("Exceptional value does not have an exponent");
- }
-
- @Override
- public int getDigits(char[] digits) {
- throw new IllegalArgumentException("Exceptional value does not have digits");
- }
-
- @Override
- public boolean isNegative() {
- return isNegative;
- }
-
- @Override
- public boolean isExceptional() {
- return true;
- }
-
- @Override
- public boolean digitsRoundedUp() {
- throw new IllegalArgumentException("Exceptional value is not rounded");
- }
-
- @Override
- public boolean decimalDigitsExact() {
- throw new IllegalArgumentException("Exceptional value is not exact");
- }
- }
-
- private static final String INFINITY_REP = "Infinity";
- private static final int INFINITY_LENGTH = INFINITY_REP.length();
- private static final String NAN_REP = "NaN";
- private static final int NAN_LENGTH = NAN_REP.length();
-
- private static final BinaryToASCIIConverter B2AC_POSITIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer(INFINITY_REP, false);
- private static final BinaryToASCIIConverter B2AC_NEGATIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer("-" + INFINITY_REP, true);
- private static final BinaryToASCIIConverter B2AC_NOT_A_NUMBER = new ExceptionalBinaryToASCIIBuffer(NAN_REP, false);
- private static final BinaryToASCIIConverter B2AC_POSITIVE_ZERO = new BinaryToASCIIBuffer(false, new char[]{'0'});
- private static final BinaryToASCIIConverter B2AC_NEGATIVE_ZERO = new BinaryToASCIIBuffer(true, new char[]{'0'});
-
- /**
- * A buffered implementation of <code>BinaryToASCIIConverter</code>.
- */
- static class BinaryToASCIIBuffer implements BinaryToASCIIConverter {
- private boolean isNegative;
- private int decExponent;
- private int firstDigitIndex;
- private int nDigits;
- private final char[] digits;
- private final char[] buffer = new char[26];
-
- //
- // The fields below provide additional information about the result of
- // the binary to decimal digits conversion done in dtoa() and roundup()
- // methods. They are changed if needed by those two methods.
- //
-
- // True if the dtoa() binary to decimal conversion was exact.
- private boolean exactDecimalConversion = false;
-
- // True if the result of the binary to decimal conversion was rounded-up
- // at the end of the conversion process, i.e. roundUp() method was called.
- private boolean decimalDigitsRoundedUp = false;
-
- /**
- * Default constructor; used for non-zero values,
- * <code>BinaryToASCIIBuffer</code> may be thread-local and reused
- */
- BinaryToASCIIBuffer(){
- this.digits = new char[20];
- }
-
- /**
- * Creates a specialized value (positive and negative zeros).
- */
- BinaryToASCIIBuffer(boolean isNegative, char[] digits){
- this.isNegative = isNegative;
- this.decExponent = 0;
- this.digits = digits;
- this.firstDigitIndex = 0;
- this.nDigits = digits.length;
- }
-
- @Override
- public String toJavaFormatString() {
- int len = getChars(buffer);
- return new String(buffer, 0, len);
- }
-
- @Override
- public void appendTo(Appendable buf) {
- int len = getChars(buffer);
- if (buf instanceof StringBuilder) {
- ((StringBuilder) buf).append(buffer, 0, len);
- } else if (buf instanceof StringBuffer) {
- ((StringBuffer) buf).append(buffer, 0, len);
- } else {
- assert false;
- }
- }
-
- @Override
- public int getDecimalExponent() {
- return decExponent;
- }
-
- @Override
- public int getDigits(char[] digits) {
- System.arraycopy(this.digits,firstDigitIndex,digits,0,this.nDigits);
- return this.nDigits;
- }
-
- @Override
- public boolean isNegative() {
- return isNegative;
- }
-
- @Override
- public boolean isExceptional() {
- return false;
- }
-
- @Override
- public boolean digitsRoundedUp() {
- return decimalDigitsRoundedUp;
- }
-
- @Override
- public boolean decimalDigitsExact() {
- return exactDecimalConversion;
- }
-
- private void setSign(boolean isNegative) {
- this.isNegative = isNegative;
- }
-
- /**
- * This is the easy subcase --
- * all the significant bits, after scaling, are held in lvalue.
- * negSign and decExponent tell us what processing and scaling
- * has already been done. Exceptional cases have already been
- * stripped out.
- * 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, int insignificantDigits ){
- if ( insignificantDigits != 0 ){
- // Discard non-significant low-order bits, while rounding,
- // up to insignificant value.
- long pow10 = FDBigInteger.LONG_5_POW[insignificantDigits] << insignificantDigits; // 10^i == 5^i * 2^i;
- long residue = lvalue % pow10;
- lvalue /= pow10;
- decExponent += insignificantDigits;
- if ( residue >= (pow10>>1) ){
- // round up based on the low-order bits we're discarding
- lvalue++;
- }
- }
- int digitno = digits.length -1;
- int c;
- if ( lvalue <= Integer.MAX_VALUE ){
- assert lvalue > 0L : lvalue; // lvalue <= 0
- // even easier subcase!
- // can do int arithmetic rather than long!
- int ivalue = (int)lvalue;
- c = ivalue%10;
- ivalue /= 10;
- while ( c == 0 ){
- decExponent++;
- c = ivalue%10;
- ivalue /= 10;
- }
- while ( ivalue != 0){
- digits[digitno--] = (char)(c+'0');
- decExponent++;
- c = ivalue%10;
- ivalue /= 10;
- }
- digits[digitno] = (char)(c+'0');
- } else {
- // same algorithm as above (same bugs, too )
- // but using long arithmetic.
- c = (int)(lvalue%10L);
- lvalue /= 10L;
- while ( c == 0 ){
- decExponent++;
- c = (int)(lvalue%10L);
- lvalue /= 10L;
- }
- while ( lvalue != 0L ){
- digits[digitno--] = (char)(c+'0');
- decExponent++;
- c = (int)(lvalue%10L);
- lvalue /= 10;
- }
- digits[digitno] = (char)(c+'0');
- }
- this.decExponent = decExponent+1;
- this.firstDigitIndex = digitno;
- this.nDigits = this.digits.length - digitno;
- }
-
- private void dtoa( int binExp, long fractBits, int nSignificantBits, boolean isCompatibleFormat)
- {
- assert fractBits > 0 ; // fractBits here can't be zero or negative
- assert (fractBits & FRACT_HOB)!=0 ; // Hi-order bit should be set
- // Examine number. Determine if it is an easy case,
- // which we can do pretty trivially using float/long conversion,
- // or whether we must do real work.
- final int tailZeros = Long.numberOfTrailingZeros(fractBits);
-
- // number of significant bits of fractBits;
- final int nFractBits = EXP_SHIFT+1-tailZeros;
-
- // reset flags to default values as dtoa() does not always set these
- // flags and a prior call to dtoa() might have set them to incorrect
- // values with respect to the current state.
- decimalDigitsRoundedUp = false;
- exactDecimalConversion = false;
-
- // number of significant bits to the right of the point.
- int nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
- if ( binExp <= MAX_SMALL_BIN_EXP && binExp >= MIN_SMALL_BIN_EXP ){
- // Look more closely at the number to decide if,
- // with scaling by 10^nTinyBits, the result will fit in
- // a long.
- if ( (nTinyBits < FDBigInteger.LONG_5_POW.length) && ((nFractBits + N_5_BITS[nTinyBits]) < 64 ) ){
- //
- // We can do this:
- // take the fraction bits, which are normalized.
- // (a) nTinyBits == 0: Shift left or right appropriately
- // to align the binary point at the extreme right, i.e.
- // where a long int point is expected to be. The integer
- // result is easily converted to a string.
- // (b) nTinyBits > 0: Shift right by EXP_SHIFT-nFractBits,
- // which effectively converts to long and scales by
- // 2^nTinyBits. Then multiply by 5^nTinyBits to
- // complete the scaling. We know this won't overflow
- // because we just counted the number of bits necessary
- // in the result. The integer you get from this can
- // then be converted to a string pretty easily.
- //
- if ( nTinyBits == 0 ) {
- int insignificant;
- if ( binExp > nSignificantBits ){
- insignificant = insignificantDigitsForPow2(binExp-nSignificantBits-1);
- } else {
- insignificant = 0;
- }
- if ( binExp >= EXP_SHIFT ){
- fractBits <<= (binExp-EXP_SHIFT);
- } else {
- fractBits >>>= (EXP_SHIFT-binExp) ;
- }
- developLongDigits( 0, fractBits, insignificant );
- return;
- }
- //
- // The following causes excess digits to be printed
- // out in the single-float case. Our manipulation of
- // halfULP here is apparently not correct. If we
- // better understand how this works, perhaps we can
- // use this special case again. But for the time being,
- // we do not.
- // else {
- // fractBits >>>= EXP_SHIFT+1-nFractBits;
- // fractBits//= long5pow[ nTinyBits ];
- // halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
- // developLongDigits( -nTinyBits, fractBits, insignificantDigits(halfULP) );
- // return;
- // }
- //
- }
- }
- //
- // This is the hard case. We are going to compute large positive
- // integers B and S and integer decExp, s.t.
- // d = ( B / S )// 10^decExp
- // 1 <= B / S < 10
- // Obvious choices are:
- // decExp = floor( log10(d) )
- // B = d// 2^nTinyBits// 10^max( 0, -decExp )
- // S = 10^max( 0, decExp)// 2^nTinyBits
- // (noting that nTinyBits has already been forced to non-negative)
- // I am also going to compute a large positive integer
- // M = (1/2^nSignificantBits)// 2^nTinyBits// 10^max( 0, -decExp )
- // i.e. M is (1/2) of the ULP of d, scaled like B.
- // When we iterate through dividing B/S and picking off the
- // quotient bits, we will know when to stop when the remainder
- // is <= M.
- //
- // We keep track of powers of 2 and powers of 5.
- //
- int decExp = estimateDecExp(fractBits,binExp);
- int B2, B5; // powers of 2 and powers of 5, respectively, in B
- int S2, S5; // powers of 2 and powers of 5, respectively, in S
- int M2, M5; // powers of 2 and powers of 5, respectively, in M
-
- B5 = Math.max( 0, -decExp );
- B2 = B5 + nTinyBits + binExp;
-
- S5 = Math.max( 0, decExp );
- S2 = S5 + nTinyBits;
-
- M5 = B5;
- M2 = B2 - nSignificantBits;
-
- //
- // the long integer fractBits contains the (nFractBits) interesting
- // bits from the mantissa of d ( hidden 1 added if necessary) followed
- // by (EXP_SHIFT+1-nFractBits) zeros. In the interest of compactness,
- // I will shift out those zeros before turning fractBits into a
- // FDBigInteger. The resulting whole number will be
- // d * 2^(nFractBits-1-binExp).
- //
- fractBits >>>= tailZeros;
- B2 -= nFractBits-1;
- int common2factor = Math.min( B2, S2 );
- B2 -= common2factor;
- S2 -= common2factor;
- M2 -= common2factor;
-
- //
- // HACK!! For exact powers of two, the next smallest number
- // is only half as far away as we think (because the meaning of
- // ULP changes at power-of-two bounds) for this reason, we
- // hack M2. Hope this works.
- //
- if ( nFractBits == 1 ) {
- M2 -= 1;
- }
-
- if ( M2 < 0 ){
- // oops.
- // since we cannot scale M down far enough,
- // we must scale the other values up.
- B2 -= M2;
- S2 -= M2;
- M2 = 0;
- }
- //
- // Construct, Scale, iterate.
- // Some day, we'll write a stopping test that takes
- // account of the asymmetry of the spacing of floating-point
- // numbers below perfect powers of 2
- // 26 Sept 96 is not that day.
- // So we use a symmetric test.
- //
- int ndigit = 0;
- boolean low, high;
- long lowDigitDifference;
- int q;
-
- //
- // Detect the special cases where all the numbers we are about
- // to compute will fit in int or long integers.
- // In these cases, we will avoid doing FDBigInteger arithmetic.
- // We use the same algorithms, except that we "normalize"
- // our FDBigIntegers before iterating. This is to make division easier,
- // as it makes our fist guess (quotient of high-order words)
- // more accurate!
- //
- // Some day, we'll write a stopping test that takes
- // account of the asymmetry of the spacing of floating-point
- // numbers below perfect powers of 2
- // 26 Sept 96 is not that day.
- // So we use a symmetric test.
- //
- // binary digits needed to represent B, approx.
- int Bbits = nFractBits + B2 + (( B5 < N_5_BITS.length )? N_5_BITS[B5] : ( B5*3 ));
-
- // binary digits needed to represent 10*S, approx.
- int tenSbits = S2+1 + (( (S5+1) < N_5_BITS.length )? N_5_BITS[(S5+1)] : ( (S5+1)*3 ));
- if ( Bbits < 64 && tenSbits < 64){
- if ( Bbits < 32 && tenSbits < 32){
- // wa-hoo! They're all ints!
- int b = ((int)fractBits * FDBigInteger.SMALL_5_POW[B5] ) << B2;
- int s = FDBigInteger.SMALL_5_POW[S5] << S2;
- int m = FDBigInteger.SMALL_5_POW[M5] << M2;
- int tens = s * 10;
- //
- // Unroll the first iteration. If our decExp estimate
- // was too high, our first quotient will be zero. In this
- // case, we discard it and decrement decExp.
- //
- ndigit = 0;
- q = b / s;
- b = 10 * ( b % s );
- m *= 10;
- low = (b < m );
- high = (b+m > tens );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- //
- // HACK! Java spec sez that we always have at least
- // one digit after the . in either F- or E-form output.
- // Thus we will need more than one digit if we're using
- // E-form
- //
- if ( !isCompatibleFormat ||decExp < -3 || decExp >= 8 ){
- high = low = false;
- }
- while( ! low && ! high ){
- q = b / s;
- b = 10 * ( b % s );
- m *= 10;
- assert q < 10 : q; // excessively large digit
- if ( m > 0L ){
- low = (b < m );
- high = (b+m > tens );
- } else {
- // hack -- m might overflow!
- // in this case, it is certainly > b,
- // which won't
- // and b+m > tens, too, since that has overflowed
- // either!
- low = true;
- high = true;
- }
- digits[ndigit++] = (char)('0' + q);
- }
- lowDigitDifference = (b<<1) - tens;
- exactDecimalConversion = (b == 0);
- } else {
- // still good! they're all longs!
- long b = (fractBits * FDBigInteger.LONG_5_POW[B5] ) << B2;
- long s = FDBigInteger.LONG_5_POW[S5] << S2;
- long m = FDBigInteger.LONG_5_POW[M5] << M2;
- long tens = s * 10L;
- //
- // Unroll the first iteration. If our decExp estimate
- // was too high, our first quotient will be zero. In this
- // case, we discard it and decrement decExp.
- //
- ndigit = 0;
- q = (int) ( b / s );
- b = 10L * ( b % s );
- m *= 10L;
- low = (b < m );
- high = (b+m > tens );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- //
- // HACK! Java spec sez that we always have at least
- // one digit after the . in either F- or E-form output.
- // Thus we will need more than one digit if we're using
- // E-form
- //
- if ( !isCompatibleFormat || decExp < -3 || decExp >= 8 ){
- high = low = false;
- }
- while( ! low && ! high ){
- q = (int) ( b / s );
- b = 10 * ( b % s );
- m *= 10;
- assert q < 10 : q; // excessively large digit
- if ( m > 0L ){
- low = (b < m );
- high = (b+m > tens );
- } else {
- // hack -- m might overflow!
- // in this case, it is certainly > b,
- // which won't
- // and b+m > tens, too, since that has overflowed
- // either!
- low = true;
- high = true;
- }
- digits[ndigit++] = (char)('0' + q);
- }
- lowDigitDifference = (b<<1) - tens;
- exactDecimalConversion = (b == 0);
- }
- } else {
- //
- // We really must do FDBigInteger arithmetic.
- // Fist, construct our FDBigInteger initial values.
- //
- FDBigInteger Sval = FDBigInteger.valueOfPow52(S5, S2);
- int shiftBias = Sval.getNormalizationBias();
- Sval = Sval.leftShift(shiftBias); // normalize so that division works better
-
- FDBigInteger Bval = FDBigInteger.valueOfMulPow52(fractBits, B5, B2 + shiftBias);
- FDBigInteger Mval = FDBigInteger.valueOfPow52(M5 + 1, M2 + shiftBias + 1);
-
- FDBigInteger tenSval = FDBigInteger.valueOfPow52(S5 + 1, S2 + shiftBias + 1); //Sval.mult( 10 );
- //
- // Unroll the first iteration. If our decExp estimate
- // was too high, our first quotient will be zero. In this
- // case, we discard it and decrement decExp.
- //
- ndigit = 0;
- q = Bval.quoRemIteration( Sval );
- low = (Bval.cmp( Mval ) < 0);
- high = tenSval.addAndCmp(Bval,Mval)<=0;
-
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- //
- // HACK! Java spec sez that we always have at least
- // one digit after the . in either F- or E-form output.
- // Thus we will need more than one digit if we're using
- // E-form
- //
- if (!isCompatibleFormat || decExp < -3 || decExp >= 8 ){
- high = low = false;
- }
- while( ! low && ! high ){
- q = Bval.quoRemIteration( Sval );
- assert q < 10 : q; // excessively large digit
- Mval = Mval.multBy10(); //Mval = Mval.mult( 10 );
- low = (Bval.cmp( Mval ) < 0);
- high = tenSval.addAndCmp(Bval,Mval)<=0;
- digits[ndigit++] = (char)('0' + q);
- }
- if ( high && low ){
- Bval = Bval.leftShift(1);
- lowDigitDifference = Bval.cmp(tenSval);
- } else {
- lowDigitDifference = 0L; // this here only for flow analysis!
- }
- exactDecimalConversion = (Bval.cmp( FDBigInteger.ZERO ) == 0);
- }
- this.decExponent = decExp+1;
- this.firstDigitIndex = 0;
- this.nDigits = ndigit;
- //
- // Last digit gets rounded based on stopping condition.
- //
- if ( high ){
- if ( low ){
- if ( lowDigitDifference == 0L ){
- // it's a tie!
- // choose based on which digits we like.
- if ( (digits[firstDigitIndex+nDigits-1]&1) != 0 ) {
- roundup();
- }
- } else if ( lowDigitDifference > 0 ){
- roundup();
- }
- } else {
- roundup();
- }
- }
- }
-
- // add one to the least significant digit.
- // in the unlikely event there is a carry out, deal with it.
- // assert that this will only happen where there
- // is only one digit, e.g. (float)1e-44 seems to do it.
- //
- private void roundup() {
- int i = (firstDigitIndex + nDigits - 1);
- int q = digits[i];
- if (q == '9') {
- while (q == '9' && i > firstDigitIndex) {
- digits[i] = '0';
- q = digits[--i];
- }
- if (q == '9') {
- // carryout! High-order 1, rest 0s, larger exp.
- decExponent += 1;
- digits[firstDigitIndex] = '1';
- return;
- }
- // else fall through.
- }
- digits[i] = (char) (q + 1);
- decimalDigitsRoundedUp = true;
- }
-
- /**
- * Estimate decimal exponent. (If it is small-ish,
- * we could double-check.)
- *
- * First, scale the mantissa bits such that 1 <= d2 < 2.
- * We are then going to estimate
- * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5)
- * and so we can estimate
- * log10(d) ~=~ log10(d2) + binExp * log10(2)
- * take the floor and call it decExp.
- */
- static int estimateDecExp(long fractBits, int binExp) {
- double d2 = Double.longBitsToDouble( EXP_ONE | ( fractBits & DoubleConsts.SIGNIF_BIT_MASK ) );
- double d = (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981;
- long dBits = Double.doubleToRawLongBits(d); //can't be NaN here so use raw
- int exponent = (int)((dBits & DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT) - DoubleConsts.EXP_BIAS;
- boolean isNegative = (dBits & DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
- if(exponent>=0 && exponent<52) { // hot path
- long mask = DoubleConsts.SIGNIF_BIT_MASK >> exponent;
- int r = (int)(( (dBits&DoubleConsts.SIGNIF_BIT_MASK) | FRACT_HOB )>>(EXP_SHIFT-exponent));
- return isNegative ? (((mask & dBits) == 0L ) ? -r : -r-1 ) : r;
- } else if (exponent < 0) {
- return (((dBits&~DoubleConsts.SIGN_BIT_MASK) == 0) ? 0 :
- ( (isNegative) ? -1 : 0) );
- } else { //if (exponent >= 52)
- return (int)d;
- }
- }
-
- private static int insignificantDigits(int insignificant) {
- int i;
- for ( i = 0; insignificant >= 10L; i++ ) {
- insignificant /= 10L;
- }
- return i;
- }
-
- /**
- * Calculates
- * <pre>
- * insignificantDigitsForPow2(v) == insignificantDigits(1L<<v)
- * </pre>
- */
- private static int insignificantDigitsForPow2(int p2) {
- if(p2>1 && p2 < insignificantDigitsNumber.length) {
- return insignificantDigitsNumber[p2];
- }
- return 0;
- }
-
- /**
- * If insignificant==(1L << ixd)
- * i = insignificantDigitsNumber[idx] is the same as:
- * int i;
- * for ( i = 0; insignificant >= 10L; i++ )
- * insignificant /= 10L;
- */
- private static int[] insignificantDigitsNumber = {
- 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3,
- 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
- 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11,
- 12, 12, 12, 12, 13, 13, 13, 14, 14, 14,
- 15, 15, 15, 15, 16, 16, 16, 17, 17, 17,
- 18, 18, 18, 19
- };
-
- // approximately ceil( log2( long5pow[i] ) )
- private static final int[] N_5_BITS = {
- 0,
- 3,
- 5,
- 7,
- 10,
- 12,
- 14,
- 17,
- 19,
- 21,
- 24,
- 26,
- 28,
- 31,
- 33,
- 35,
- 38,
- 40,
- 42,
- 45,
- 47,
- 49,
- 52,
- 54,
- 56,
- 59,
- 61,
- };
-
- private int getChars(char[] result) {
- assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
- int i = 0;
- if (isNegative) {
- result[0] = '-';
- i = 1;
- }
- if (decExponent > 0 && decExponent < 8) {
- // print digits.digits.
- int charLength = Math.min(nDigits, decExponent);
- System.arraycopy(digits, firstDigitIndex, result, i, charLength);
- i += charLength;
- if (charLength < decExponent) {
- charLength = decExponent - charLength;
- Arrays.fill(result,i,i+charLength,'0');
- i += charLength;
- result[i++] = '.';
- result[i++] = '0';
- } else {
- result[i++] = '.';
- if (charLength < nDigits) {
- int t = nDigits - charLength;
- System.arraycopy(digits, firstDigitIndex+charLength, result, i, t);
- i += t;
- } else {
- result[i++] = '0';
- }
- }
- } else if (decExponent <= 0 && decExponent > -3) {
- result[i++] = '0';
- result[i++] = '.';
- if (decExponent != 0) {
- Arrays.fill(result, i, i-decExponent, '0');
- i -= decExponent;
- }
- System.arraycopy(digits, firstDigitIndex, result, i, nDigits);
- i += nDigits;
- } else {
- result[i++] = digits[firstDigitIndex];
- result[i++] = '.';
- if (nDigits > 1) {
- System.arraycopy(digits, firstDigitIndex+1, result, i, nDigits - 1);
- i += nDigits - 1;
- } else {
- result[i++] = '0';
- }
- result[i++] = 'E';
- int e;
- if (decExponent <= 0) {
- result[i++] = '-';
- e = -decExponent + 1;
- } else {
- e = decExponent - 1;
- }
- // decExponent has 1, 2, or 3, digits
- if (e <= 9) {
- result[i++] = (char) (e + '0');
- } else if (e <= 99) {
- result[i++] = (char) (e / 10 + '0');
- result[i++] = (char) (e % 10 + '0');
- } else {
- result[i++] = (char) (e / 100 + '0');
- e %= 100;
- result[i++] = (char) (e / 10 + '0');
- result[i++] = (char) (e % 10 + '0');
- }
- }
- return i;
- }
-
- }
-
- private static final ThreadLocal<BinaryToASCIIBuffer> threadLocalBinaryToASCIIBuffer =
- new ThreadLocal<BinaryToASCIIBuffer>() {
- @Override
- protected BinaryToASCIIBuffer initialValue() {
- return new BinaryToASCIIBuffer();
- }
- };
-
- private static BinaryToASCIIBuffer getBinaryToASCIIBuffer() {
- return threadLocalBinaryToASCIIBuffer.get();
- }
-
- /**
- * A converter which can process an ASCII <code>String</code> representation
- * of a single or double precision floating point value into a
- * <code>float</code> or a <code>double</code>.
- */
- interface ASCIIToBinaryConverter {
-
- double doubleValue();
-
- float floatValue();
-
- }
-
- /**
- * A <code>ASCIIToBinaryConverter</code> container for a <code>double</code>.
- */
- static class PreparedASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
- private final double doubleVal;
- private final float floatVal;
-
- public PreparedASCIIToBinaryBuffer(double doubleVal, float floatVal) {
- this.doubleVal = doubleVal;
- this.floatVal = floatVal;
- }
-
- @Override
- public double doubleValue() {
- return doubleVal;
- }
-
- @Override
- public float floatValue() {
- return floatVal;
- }
- }
-
- static final ASCIIToBinaryConverter A2BC_POSITIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
- static final ASCIIToBinaryConverter A2BC_NEGATIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
- static final ASCIIToBinaryConverter A2BC_NOT_A_NUMBER = new PreparedASCIIToBinaryBuffer(Double.NaN, Float.NaN);
- static final ASCIIToBinaryConverter A2BC_POSITIVE_ZERO = new PreparedASCIIToBinaryBuffer(0.0d, 0.0f);
- static final ASCIIToBinaryConverter A2BC_NEGATIVE_ZERO = new PreparedASCIIToBinaryBuffer(-0.0d, -0.0f);
-
- /**
- * A buffered implementation of <code>ASCIIToBinaryConverter</code>.
- */
- static class ASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
- boolean isNegative;
- int decExponent;
- char digits[];
- int nDigits;
-
- ASCIIToBinaryBuffer( boolean negSign, int decExponent, char[] digits, int n)
- {
- this.isNegative = negSign;
- this.decExponent = decExponent;
- this.digits = digits;
- this.nDigits = n;
- }
-
- /**
- * Takes a FloatingDecimal, which we presumably just scanned in,
- * and finds out what its value is, as a double.
- *
- * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
- * ROUNDING DIRECTION in case the result is really destined
- * for a single-precision float.
- */
- @Override
- public double doubleValue() {
- int kDigits = Math.min(nDigits, MAX_DECIMAL_DIGITS + 1);
- //
- // convert the lead kDigits to a long integer.
- //
- // (special performance hack: start to do it using int)
- int iValue = (int) digits[0] - (int) '0';
- int iDigits = Math.min(kDigits, INT_DECIMAL_DIGITS);
- for (int i = 1; i < iDigits; i++) {
- iValue = iValue * 10 + (int) digits[i] - (int) '0';
- }
- long lValue = (long) iValue;
- for (int i = iDigits; i < kDigits; i++) {
- lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
- }
- double dValue = (double) lValue;
- int exp = decExponent - kDigits;
- //
- // lValue now contains a long integer with the value of
- // the first kDigits digits of the number.
- // dValue contains the (double) of the same.
- //
-
- if (nDigits <= MAX_DECIMAL_DIGITS) {
- //
- // possibly an easy case.
- // We know that the digits can be represented
- // exactly. And if the exponent isn't too outrageous,
- // the whole thing can be done with one operation,
- // thus one rounding error.
- // Note that all our constructors trim all leading and
- // trailing zeros, so simple values (including zero)
- // will always end up here
- //
- if (exp == 0 || dValue == 0.0) {
- return (isNegative) ? -dValue : dValue; // small floating integer
- }
- else if (exp >= 0) {
- if (exp <= MAX_SMALL_TEN) {
- //
- // Can get the answer with one operation,
- // thus one roundoff.
- //
- double rValue = dValue * SMALL_10_POW[exp];
- return (isNegative) ? -rValue : rValue;
- }
- int slop = MAX_DECIMAL_DIGITS - kDigits;
- if (exp <= MAX_SMALL_TEN + slop) {
- //
- // We can multiply dValue by 10^(slop)
- // and it is still "small" and exact.
- // Then we can multiply by 10^(exp-slop)
- // with one rounding.
- //
- dValue *= SMALL_10_POW[slop];
- double rValue = dValue * SMALL_10_POW[exp - slop];
- return (isNegative) ? -rValue : rValue;
- }
- //
- // Else we have a hard case with a positive exp.
- //
- } else {
- if (exp >= -MAX_SMALL_TEN) {
- //
- // Can get the answer in one division.
- //
- double rValue = dValue / SMALL_10_POW[-exp];
- return (isNegative) ? -rValue : rValue;
- }
- //
- // Else we have a hard case with a negative exp.
- //
- }
- }
-
- //
- // Harder cases:
- // The sum of digits plus exponent is greater than
- // what we think we can do with one error.
- //
- // Start by approximating the right answer by,
- // naively, scaling by powers of 10.
- //
- if (exp > 0) {
- if (decExponent > MAX_DECIMAL_EXPONENT + 1) {
- //
- // Lets face it. This is going to be
- // Infinity. Cut to the chase.
- //
- return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
- }
- if ((exp & 15) != 0) {
- dValue *= SMALL_10_POW[exp & 15];
- }
- if ((exp >>= 4) != 0) {
- int j;
- for (j = 0; exp > 1; j++, exp >>= 1) {
- if ((exp & 1) != 0) {
- dValue *= BIG_10_POW[j];
- }
- }
- //
- // The reason for the weird exp > 1 condition
- // in the above loop was so that the last multiply
- // would get unrolled. We handle it here.
- // It could overflow.
- //
- double t = dValue * BIG_10_POW[j];
- if (Double.isInfinite(t)) {
- //
- // It did overflow.
- // Look more closely at the result.
- // If the exponent is just one too large,
- // then use the maximum finite as our estimate
- // value. Else call the result infinity
- // and punt it.
- // ( I presume this could happen because
- // rounding forces the result here to be
- // an ULP or two larger than
- // Double.MAX_VALUE ).
- //
- t = dValue / 2.0;
- t *= BIG_10_POW[j];
- if (Double.isInfinite(t)) {
- return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
- }
- t = Double.MAX_VALUE;
- }
- dValue = t;
- }
- } else if (exp < 0) {
- exp = -exp;
- if (decExponent < MIN_DECIMAL_EXPONENT - 1) {
- //
- // Lets face it. This is going to be
- // zero. Cut to the chase.
- //
- return (isNegative) ? -0.0 : 0.0;
- }
- if ((exp & 15) != 0) {
- dValue /= SMALL_10_POW[exp & 15];
- }
- if ((exp >>= 4) != 0) {
- int j;
- for (j = 0; exp > 1; j++, exp >>= 1) {
- if ((exp & 1) != 0) {
- dValue *= TINY_10_POW[j];
- }
- }
- //
- // The reason for the weird exp > 1 condition
- // in the above loop was so that the last multiply
- // would get unrolled. We handle it here.
- // It could underflow.
- //
- double t = dValue * TINY_10_POW[j];
- if (t == 0.0) {
- //
- // It did underflow.
- // Look more closely at the result.
- // If the exponent is just one too small,
- // then use the minimum finite as our estimate
- // value. Else call the result 0.0
- // and punt it.
- // ( I presume this could happen because
- // rounding forces the result here to be
- // an ULP or two less than
- // Double.MIN_VALUE ).
- //
- t = dValue * 2.0;
- t *= TINY_10_POW[j];
- if (t == 0.0) {
- return (isNegative) ? -0.0 : 0.0;
- }
- t = Double.MIN_VALUE;
- }
- dValue = t;
- }
- }
-
- //
- // dValue is now approximately the result.
- // The hard part is adjusting it, by comparison
- // with FDBigInteger arithmetic.
- // Formulate the EXACT big-number result as
- // bigD0 * 10^exp
- //
- if (nDigits > MAX_NDIGITS) {
- nDigits = MAX_NDIGITS + 1;
- digits[MAX_NDIGITS] = '1';
- }
- FDBigInteger bigD0 = new FDBigInteger(lValue, digits, kDigits, nDigits);
- exp = decExponent - nDigits;
-
- long ieeeBits = Double.doubleToRawLongBits(dValue); // IEEE-754 bits of double candidate
- final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
- final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
- bigD0 = bigD0.multByPow52(D5, 0);
- bigD0.makeImmutable(); // prevent bigD0 modification inside correctionLoop
- FDBigInteger bigD = null;
- int prevD2 = 0;
-
- correctionLoop:
- while (true) {
- // here ieeeBits can't be NaN, Infinity or zero
- int binexp = (int) (ieeeBits >>> EXP_SHIFT);
- long bigBbits = ieeeBits & DoubleConsts.SIGNIF_BIT_MASK;
- if (binexp > 0) {
- bigBbits |= FRACT_HOB;
- } else { // Normalize denormalized numbers.
- assert bigBbits != 0L : bigBbits; // doubleToBigInt(0.0)
- int leadingZeros = Long.numberOfLeadingZeros(bigBbits);
- int shift = leadingZeros - (63 - EXP_SHIFT);
- bigBbits <<= shift;
- binexp = 1 - shift;
- }
- binexp -= DoubleConsts.EXP_BIAS;
- int lowOrderZeros = Long.numberOfTrailingZeros(bigBbits);
- bigBbits >>>= lowOrderZeros;
- final int bigIntExp = binexp - EXP_SHIFT + lowOrderZeros;
- final int bigIntNBits = EXP_SHIFT + 1 - lowOrderZeros;
-
- //
- // Scale bigD, bigB appropriately for
- // big-integer operations.
- // Naively, we multiply by powers of ten
- // and powers of two. What we actually do
- // is keep track of the powers of 5 and
- // powers of 2 we would use, then factor out
- // common divisors before doing the work.
- //
- int B2 = B5; // powers of 2 in bigB
- int D2 = D5; // powers of 2 in bigD
- int Ulp2; // powers of 2 in halfUlp.
- if (bigIntExp >= 0) {
- B2 += bigIntExp;
- } else {
- D2 -= bigIntExp;
- }
- Ulp2 = B2;
- // shift bigB and bigD left by a number s. t.
- // halfUlp is still an integer.
- int hulpbias;
- if (binexp <= -DoubleConsts.EXP_BIAS) {
- // This is going to be a denormalized number
- // (if not actually zero).
- // half an ULP is at 2^-(DoubleConsts.EXP_BIAS+EXP_SHIFT+1)
- hulpbias = binexp + lowOrderZeros + DoubleConsts.EXP_BIAS;
- } else {
- hulpbias = 1 + lowOrderZeros;
- }
- B2 += hulpbias;
- D2 += hulpbias;
- // if there are common factors of 2, we might just as well
- // factor them out, as they add nothing useful.
- int common2 = Math.min(B2, Math.min(D2, Ulp2));
- B2 -= common2;
- D2 -= common2;
- Ulp2 -= common2;
- // do multiplications by powers of 5 and 2
- FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
- if (bigD == null || prevD2 != D2) {
- bigD = bigD0.leftShift(D2);
- prevD2 = D2;
- }
- //
- // to recap:
- // bigB is the scaled-big-int version of our floating-point
- // candidate.
- // bigD is the scaled-big-int version of the exact value
- // as we understand it.
- // halfUlp is 1/2 an ulp of bigB, except for special cases
- // of exact powers of 2
- //
- // the plan is to compare bigB with bigD, and if the difference
- // is less than halfUlp, then we're satisfied. Otherwise,
- // use the ratio of difference to halfUlp to calculate a fudge
- // factor to add to the floating value, then go 'round again.
- //
- FDBigInteger diff;
- int cmpResult;
- boolean overvalue;
- if ((cmpResult = bigB.cmp(bigD)) > 0) {
- overvalue = true; // our candidate is too big.
- diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
- if ((bigIntNBits == 1) && (bigIntExp > -DoubleConsts.EXP_BIAS + 1)) {
- // candidate is a normalized exact power of 2 and
- // is too big (larger than Double.MIN_NORMAL). We will be subtracting.
- // For our purposes, ulp is the ulp of the
- // next smaller range.
- Ulp2 -= 1;
- if (Ulp2 < 0) {
- // rats. Cannot de-scale ulp this far.
- // must scale diff in other direction.
- Ulp2 = 0;
- diff = diff.leftShift(1);
- }
- }
- } else if (cmpResult < 0) {
- overvalue = false; // our candidate is too small.
- diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
- } else {
- // the candidate is exactly right!
- // this happens with surprising frequency
- break correctionLoop;
- }
- cmpResult = diff.cmpPow52(B5, Ulp2);
- if ((cmpResult) < 0) {
- // difference is small.
- // this is close enough
- break correctionLoop;
- } else if (cmpResult == 0) {
- // difference is exactly half an ULP
- // round to some other value maybe, then finish
- if ((ieeeBits & 1) != 0) { // half ties to even
- ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
- }
- 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.
- ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
- if (ieeeBits == 0 || ieeeBits == DoubleConsts.EXP_BIT_MASK) { // 0.0 or Double.POSITIVE_INFINITY
- break correctionLoop; // oops. Fell off end of range.
- }
- continue; // try again.
- }
-
- }
- if (isNegative) {
- ieeeBits |= DoubleConsts.SIGN_BIT_MASK;
- }
- return Double.longBitsToDouble(ieeeBits);
- }
-
- /**
- * Takes a FloatingDecimal, which we presumably just scanned in,
- * and finds out what its value is, as a float.
- * This is distinct from doubleValue() to avoid the extremely
- * unlikely case of a double rounding error, wherein the conversion
- * to double has one rounding error, and the conversion of that double
- * to a float has another rounding error, IN THE WRONG DIRECTION,
- * ( because of the preference to a zero low-order bit ).
- */
- @Override
- public float floatValue() {
- int kDigits = Math.min(nDigits, SINGLE_MAX_DECIMAL_DIGITS + 1);
- //
- // convert the lead kDigits to an integer.
- //
- int iValue = (int) digits[0] - (int) '0';
- for (int i = 1; i < kDigits; i++) {
- iValue = iValue * 10 + (int) digits[i] - (int) '0';
- }
- float fValue = (float) iValue;
- int exp = decExponent - kDigits;
- //
- // iValue now contains an integer with the value of
- // the first kDigits digits of the number.
- // fValue contains the (float) of the same.
- //
-
- if (nDigits <= SINGLE_MAX_DECIMAL_DIGITS) {
- //
- // possibly an easy case.
- // We know that the digits can be represented
- // exactly. And if the exponent isn't too outrageous,
- // the whole thing can be done with one operation,
- // thus one rounding error.
- // Note that all our constructors trim all leading and
- // trailing zeros, so simple values (including zero)
- // will always end up here.
- //
- if (exp == 0 || fValue == 0.0f) {
- return (isNegative) ? -fValue : fValue; // small floating integer
- } else if (exp >= 0) {
- if (exp <= SINGLE_MAX_SMALL_TEN) {
- //
- // Can get the answer with one operation,
- // thus one roundoff.
- //
- fValue *= SINGLE_SMALL_10_POW[exp];
- return (isNegative) ? -fValue : fValue;
- }
- int slop = SINGLE_MAX_DECIMAL_DIGITS - kDigits;
- if (exp <= SINGLE_MAX_SMALL_TEN + slop) {
- //
- // We can multiply fValue by 10^(slop)
- // and it is still "small" and exact.
- // Then we can multiply by 10^(exp-slop)
- // with one rounding.
- //
- fValue *= SINGLE_SMALL_10_POW[slop];
- fValue *= SINGLE_SMALL_10_POW[exp - slop];
- return (isNegative) ? -fValue : fValue;
- }
- //
- // Else we have a hard case with a positive exp.
- //
- } else {
- if (exp >= -SINGLE_MAX_SMALL_TEN) {
- //
- // Can get the answer in one division.
- //
- fValue /= SINGLE_SMALL_10_POW[-exp];
- return (isNegative) ? -fValue : fValue;
- }
- //
- // Else we have a hard case with a negative exp.
- //
- }
- } else if ((decExponent >= nDigits) && (nDigits + decExponent <= MAX_DECIMAL_DIGITS)) {
- //
- // In double-precision, this is an exact floating integer.
- // So we can compute to double, then shorten to float
- // with one round, and get the right answer.
- //
- // First, finish accumulating digits.
- // Then convert that integer to a double, multiply
- // by the appropriate power of ten, and convert to float.
- //
- long lValue = (long) iValue;
- for (int i = kDigits; i < nDigits; i++) {
- lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
- }
- double dValue = (double) lValue;
- exp = decExponent - nDigits;
- dValue *= SMALL_10_POW[exp];
- fValue = (float) dValue;
- return (isNegative) ? -fValue : fValue;
-
- }
- //
- // Harder cases:
- // The sum of digits plus exponent is greater than
- // what we think we can do with one error.
- //
- // Start by approximating the right answer by,
- // naively, scaling by powers of 10.
- // Scaling uses doubles to avoid overflow/underflow.
- //
- double dValue = fValue;
- if (exp > 0) {
- if (decExponent > SINGLE_MAX_DECIMAL_EXPONENT + 1) {
- //
- // Lets face it. This is going to be
- // Infinity. Cut to the chase.
- //
- return (isNegative) ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
- }
- if ((exp & 15) != 0) {
- dValue *= SMALL_10_POW[exp & 15];
- }
- if ((exp >>= 4) != 0) {
- int j;
- for (j = 0; exp > 0; j++, exp >>= 1) {
- if ((exp & 1) != 0) {
- dValue *= BIG_10_POW[j];
- }
- }
- }
- } else if (exp < 0) {
- exp = -exp;
- if (decExponent < SINGLE_MIN_DECIMAL_EXPONENT - 1) {
- //
- // Lets face it. This is going to be
- // zero. Cut to the chase.
- //
- return (isNegative) ? -0.0f : 0.0f;
- }
- if ((exp & 15) != 0) {
- dValue /= SMALL_10_POW[exp & 15];
- }
- if ((exp >>= 4) != 0) {
- int j;
- for (j = 0; exp > 0; j++, exp >>= 1) {
- if ((exp & 1) != 0) {
- dValue *= TINY_10_POW[j];
- }
- }
- }
- }
- fValue = Math.max(Float.MIN_VALUE, Math.min(Float.MAX_VALUE, (float) dValue));
-
- //
- // fValue is now approximately the result.
- // The hard part is adjusting it, by comparison
- // with FDBigInteger arithmetic.
- // Formulate the EXACT big-number result as
- // bigD0 * 10^exp
- //
- if (nDigits > SINGLE_MAX_NDIGITS) {
- nDigits = SINGLE_MAX_NDIGITS + 1;
- digits[SINGLE_MAX_NDIGITS] = '1';
- }
- FDBigInteger bigD0 = new FDBigInteger(iValue, digits, kDigits, nDigits);
- exp = decExponent - nDigits;
-
- int ieeeBits = Float.floatToRawIntBits(fValue); // IEEE-754 bits of float candidate
- final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
- final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
- bigD0 = bigD0.multByPow52(D5, 0);
- bigD0.makeImmutable(); // prevent bigD0 modification inside correctionLoop
- FDBigInteger bigD = null;
- int prevD2 = 0;
-
- correctionLoop:
- while (true) {
- // here ieeeBits can't be NaN, Infinity or zero
- int binexp = ieeeBits >>> SINGLE_EXP_SHIFT;
- int bigBbits = ieeeBits & FloatConsts.SIGNIF_BIT_MASK;
- if (binexp > 0) {
- bigBbits |= SINGLE_FRACT_HOB;
- } else { // Normalize denormalized numbers.
- assert bigBbits != 0 : bigBbits; // floatToBigInt(0.0)
- int leadingZeros = Integer.numberOfLeadingZeros(bigBbits);
- int shift = leadingZeros - (31 - SINGLE_EXP_SHIFT);
- bigBbits <<= shift;
- binexp = 1 - shift;
- }
- binexp -= FloatConsts.EXP_BIAS;
- int lowOrderZeros = Integer.numberOfTrailingZeros(bigBbits);
- bigBbits >>>= lowOrderZeros;
- final int bigIntExp = binexp - SINGLE_EXP_SHIFT + lowOrderZeros;
- final int bigIntNBits = SINGLE_EXP_SHIFT + 1 - lowOrderZeros;
-
- //
- // Scale bigD, bigB appropriately for
- // big-integer operations.
- // Naively, we multiply by powers of ten
- // and powers of two. What we actually do
- // is keep track of the powers of 5 and
- // powers of 2 we would use, then factor out
- // common divisors before doing the work.
- //
- int B2 = B5; // powers of 2 in bigB
- int D2 = D5; // powers of 2 in bigD
- int Ulp2; // powers of 2 in halfUlp.
- if (bigIntExp >= 0) {
- B2 += bigIntExp;
- } else {
- D2 -= bigIntExp;
- }
- Ulp2 = B2;
- // shift bigB and bigD left by a number s. t.
- // halfUlp is still an integer.
- int hulpbias;
- if (binexp <= -FloatConsts.EXP_BIAS) {
- // This is going to be a denormalized number
- // (if not actually zero).
- // half an ULP is at 2^-(FloatConsts.EXP_BIAS+SINGLE_EXP_SHIFT+1)
- hulpbias = binexp + lowOrderZeros + FloatConsts.EXP_BIAS;
- } else {
- hulpbias = 1 + lowOrderZeros;
- }
- B2 += hulpbias;
- D2 += hulpbias;
- // if there are common factors of 2, we might just as well
- // factor them out, as they add nothing useful.
- int common2 = Math.min(B2, Math.min(D2, Ulp2));
- B2 -= common2;
- D2 -= common2;
- Ulp2 -= common2;
- // do multiplications by powers of 5 and 2
- FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
- if (bigD == null || prevD2 != D2) {
- bigD = bigD0.leftShift(D2);
- prevD2 = D2;
- }
- //
- // to recap:
- // bigB is the scaled-big-int version of our floating-point
- // candidate.
- // bigD is the scaled-big-int version of the exact value
- // as we understand it.
- // halfUlp is 1/2 an ulp of bigB, except for special cases
- // of exact powers of 2
- //
- // the plan is to compare bigB with bigD, and if the difference
- // is less than halfUlp, then we're satisfied. Otherwise,
- // use the ratio of difference to halfUlp to calculate a fudge
- // factor to add to the floating value, then go 'round again.
- //
- FDBigInteger diff;
- int cmpResult;
- boolean overvalue;
- if ((cmpResult = bigB.cmp(bigD)) > 0) {
- overvalue = true; // our candidate is too big.
- diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
- if ((bigIntNBits == 1) && (bigIntExp > -FloatConsts.EXP_BIAS + 1)) {
- // candidate is a normalized exact power of 2 and
- // is too big (larger than Float.MIN_NORMAL). We will be subtracting.
- // For our purposes, ulp is the ulp of the
- // next smaller range.
- Ulp2 -= 1;
- if (Ulp2 < 0) {
- // rats. Cannot de-scale ulp this far.
- // must scale diff in other direction.
- Ulp2 = 0;
- diff = diff.leftShift(1);
- }
- }
- } else if (cmpResult < 0) {
- overvalue = false; // our candidate is too small.
- diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
- } else {
- // the candidate is exactly right!
- // this happens with surprising frequency
- break correctionLoop;
- }
- cmpResult = diff.cmpPow52(B5, Ulp2);
- if ((cmpResult) < 0) {
- // difference is small.
- // this is close enough
- break correctionLoop;
- } else if (cmpResult == 0) {
- // difference is exactly half an ULP
- // round to some other value maybe, then finish
- if ((ieeeBits & 1) != 0) { // half ties to even
- ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
- }
- 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.
- ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
- if (ieeeBits == 0 || ieeeBits == FloatConsts.EXP_BIT_MASK) { // 0.0 or Float.POSITIVE_INFINITY
- break correctionLoop; // oops. Fell off end of range.
- }
- continue; // try again.
- }
-
- }
- if (isNegative) {
- ieeeBits |= FloatConsts.SIGN_BIT_MASK;
- }
- return Float.intBitsToFloat(ieeeBits);
- }
-
-
- /**
- * All the positive powers of 10 that can be
- * represented exactly in double/float.
- */
- private static final double[] SMALL_10_POW = {
- 1.0e0,
- 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
- 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
- 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
- 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
- 1.0e21, 1.0e22
- };
-
- private static final float[] SINGLE_SMALL_10_POW = {
- 1.0e0f,
- 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
- 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
- };
-
- private static final double[] BIG_10_POW = {
- 1e16, 1e32, 1e64, 1e128, 1e256 };
- private static final double[] TINY_10_POW = {
- 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
-
- private static final int MAX_SMALL_TEN = SMALL_10_POW.length-1;
- private static final int SINGLE_MAX_SMALL_TEN = SINGLE_SMALL_10_POW.length-1;
-
- }
-
- /**
- * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
- * The returned object is a <code>ThreadLocal</code> variable of this class.
- *
- * @param d The double precision value to convert.
- * @return The converter.
- */
- public static BinaryToASCIIConverter getBinaryToASCIIConverter(double d) {
- return getBinaryToASCIIConverter(d, true);
- }
-
- /**
- * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
- * The returned object is a <code>ThreadLocal</code> variable of this class.
- *
- * @param d The double precision value to convert.
- * @param isCompatibleFormat
- * @return The converter.
- */
- static BinaryToASCIIConverter getBinaryToASCIIConverter(double d, boolean isCompatibleFormat) {
- long dBits = Double.doubleToRawLongBits(d);
- boolean isNegative = (dBits&DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
- long fractBits = dBits & DoubleConsts.SIGNIF_BIT_MASK;
- int binExp = (int)( (dBits&DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT );
- // Discover obvious special cases of NaN and Infinity.
- if ( binExp == (int)(DoubleConsts.EXP_BIT_MASK>>EXP_SHIFT) ) {
- if ( fractBits == 0L ){
- return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
- } else {
- return B2AC_NOT_A_NUMBER;
- }
- }
- // Finish unpacking
- // Normalize denormalized numbers.
- // Insert assumed high-order bit for normalized numbers.
- // Subtract exponent bias.
- int nSignificantBits;
- if ( binExp == 0 ){
- if ( fractBits == 0L ){
- // not a denorm, just a 0!
- return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
- }
- int leadingZeros = Long.numberOfLeadingZeros(fractBits);
- int shift = leadingZeros-(63-EXP_SHIFT);
- fractBits <<= shift;
- binExp = 1 - shift;
- nSignificantBits = 64-leadingZeros; // recall binExp is - shift count.
- } else {
- fractBits |= FRACT_HOB;
- nSignificantBits = EXP_SHIFT+1;
- }
- binExp -= DoubleConsts.EXP_BIAS;
- BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
- buf.setSign(isNegative);
- // call the routine that actually does all the hard work.
- buf.dtoa(binExp, fractBits, nSignificantBits, isCompatibleFormat);
- return buf;
- }
-
- private static BinaryToASCIIConverter getBinaryToASCIIConverter(float f) {
- int fBits = Float.floatToRawIntBits( f );
- boolean isNegative = (fBits&FloatConsts.SIGN_BIT_MASK) != 0;
- int fractBits = fBits&FloatConsts.SIGNIF_BIT_MASK;
- int binExp = (fBits&FloatConsts.EXP_BIT_MASK) >> SINGLE_EXP_SHIFT;
- // Discover obvious special cases of NaN and Infinity.
- if ( binExp == (FloatConsts.EXP_BIT_MASK>>SINGLE_EXP_SHIFT) ) {
- if ( fractBits == 0L ){
- return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
- } else {
- return B2AC_NOT_A_NUMBER;
- }
- }
- // Finish unpacking
- // Normalize denormalized numbers.
- // Insert assumed high-order bit for normalized numbers.
- // Subtract exponent bias.
- int nSignificantBits;
- if ( binExp == 0 ){
- if ( fractBits == 0 ){
- // not a denorm, just a 0!
- return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
- }
- int leadingZeros = Integer.numberOfLeadingZeros(fractBits);
- int shift = leadingZeros-(31-SINGLE_EXP_SHIFT);
- fractBits <<= shift;
- binExp = 1 - shift;
- nSignificantBits = 32 - leadingZeros; // recall binExp is - shift count.
- } else {
- fractBits |= SINGLE_FRACT_HOB;
- nSignificantBits = SINGLE_EXP_SHIFT+1;
- }
- binExp -= FloatConsts.EXP_BIAS;
- BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
- buf.setSign(isNegative);
- // call the routine that actually does all the hard work.
- buf.dtoa(binExp, ((long)fractBits)<<(EXP_SHIFT-SINGLE_EXP_SHIFT), nSignificantBits, true);
- return buf;
- }
-
- @SuppressWarnings("fallthrough")
- static ASCIIToBinaryConverter readJavaFormatString( String in ) throws NumberFormatException {
- boolean isNegative = false;
- boolean signSeen = false;
- int decExp;
- char c;
-
- parseNumber:
- try{
- in = in.trim(); // don't fool around with white space.
- // throws NullPointerException if null
- int len = in.length();
- if ( len == 0 ) {
- throw new NumberFormatException("empty String");
- }
- int i = 0;
- switch (in.charAt(i)){
- case '-':
- isNegative = true;
- //FALLTHROUGH
- case '+':
- i++;
- signSeen = true;
- }
- c = in.charAt(i);
- if(c == 'N') { // Check for NaN
- if((len-i)==NAN_LENGTH && in.indexOf(NAN_REP,i)==i) {
- return A2BC_NOT_A_NUMBER;
- }
- // something went wrong, throw exception
- break parseNumber;
- } else if(c == 'I') { // Check for Infinity strings
- if((len-i)==INFINITY_LENGTH && in.indexOf(INFINITY_REP,i)==i) {
- return isNegative? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
- }
- // something went wrong, throw exception
- break parseNumber;
- } else if (c == '0') { // check for hexadecimal floating-point number
- if (len > i+1 ) {
- char ch = in.charAt(i+1);
- if (ch == 'x' || ch == 'X' ) { // possible hex string
- return parseHexString(in);
- }
- }
- } // look for and process decimal floating-point string
-
- char[] digits = new char[ len ];
- int nDigits= 0;
- boolean decSeen = false;
- int decPt = 0;
- int nLeadZero = 0;
- int nTrailZero= 0;
-
- skipLeadingZerosLoop:
- while (i < len) {
- c = in.charAt(i);
- if (c == '0') {
- nLeadZero++;
- } else if (c == '.') {
- if (decSeen) {
- // already saw one ., this is the 2nd.
- throw new NumberFormatException("multiple points");
- }
- decPt = i;
- if (signSeen) {
- decPt -= 1;
- }
- decSeen = true;
- } else {
- break skipLeadingZerosLoop;
- }
- i++;
- }
- digitLoop:
- while (i < len) {
- c = in.charAt(i);
- if (c >= '1' && c <= '9') {
- digits[nDigits++] = c;
- nTrailZero = 0;
- } else if (c == '0') {
- digits[nDigits++] = c;
- nTrailZero++;
- } else if (c == '.') {
- if (decSeen) {
- // already saw one ., this is the 2nd.
- throw new NumberFormatException("multiple points");
- }
- decPt = i;
- if (signSeen) {
- decPt -= 1;
- }
- decSeen = true;
- } else {
- break digitLoop;
- }
- i++;
- }
- nDigits -=nTrailZero;
- //
- // At this point, we've scanned all the digits and decimal
- // point we're going to see. Trim off leading and trailing
- // zeros, which will just confuse us later, and adjust
- // our initial decimal exponent accordingly.
- // To review:
- // we have seen i total characters.
- // nLeadZero of them were zeros before any other digits.
- // nTrailZero of them were zeros after any other digits.
- // if ( decSeen ), then a . was seen after decPt characters
- // ( including leading zeros which have been discarded )
- // nDigits characters were neither lead nor trailing
- // zeros, nor point
- //
- //
- // special hack: if we saw no non-zero digits, then the
- // answer is zero!
- // Unfortunately, we feel honor-bound to keep parsing!
- //
- boolean isZero = (nDigits == 0);
- if ( isZero && nLeadZero == 0 ){
- // we saw NO DIGITS AT ALL,
- // not even a crummy 0!
- // this is not allowed.
- break parseNumber; // go throw exception
- }
- //
- // Our initial exponent is decPt, adjusted by the number of
- // discarded zeros. Or, if there was no decPt,
- // then its just nDigits adjusted by discarded trailing zeros.
- //
- if ( decSeen ){
- decExp = decPt - nLeadZero;
- } else {
- decExp = nDigits + nTrailZero;
- }
-
- //
- // Look for 'e' or 'E' and an optionally signed integer.
- //
- if ( (i < len) && (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
- int expSign = 1;
- int expVal = 0;
- int reallyBig = Integer.MAX_VALUE / 10;
- boolean expOverflow = false;
- switch( in.charAt(++i) ){
- case '-':
- expSign = -1;
- //FALLTHROUGH
- case '+':
- i++;
- }
- int expAt = i;
- expLoop:
- while ( i < len ){
- if ( expVal >= reallyBig ){
- // the next character will cause integer
- // overflow.
- expOverflow = true;
- }
- c = in.charAt(i++);
- if(c>='0' && c<='9') {
- expVal = expVal*10 + ( (int)c - (int)'0' );
- } else {
- i--; // back up.
- break expLoop; // stop parsing exponent.
- }
- }
- int expLimit = BIG_DECIMAL_EXPONENT + nDigits + nTrailZero;
- if (expOverflow || (expVal > expLimit)) {
- // There is still a chance that the exponent will be safe to
- // use: if it would eventually decrease due to a negative
- // decExp, and that number is below the limit. We check for
- // that here.
- if (!expOverflow && (expSign == 1 && decExp < 0)
- && (expVal + decExp) < expLimit) {
- // Cannot overflow: adding a positive and negative number.
- decExp += expVal;
- } else {
- //
- // The intent here is to end up with
- // infinity or zero, as appropriate.
- // The reason for yielding such a small decExponent,
- // rather than something intuitive such as
- // expSign*Integer.MAX_VALUE, is that this value
- // is subject to further manipulation in
- // doubleValue() and floatValue(), and I don't want
- // it to be able to cause overflow there!
- // (The only way we can get into trouble here is for
- // really outrageous nDigits+nTrailZero, such as 2
- // billion.)
- //
- decExp = expSign * expLimit;
- }
- } else {
- // this should not overflow, since we tested
- // for expVal > (MAX+N), where N >= abs(decExp)
- decExp = decExp + expSign*expVal;
- }
-
- // if we saw something not a digit ( or end of string )
- // after the [Ee][+-], without seeing any digits at all
- // this is certainly an error. If we saw some digits,
- // but then some trailing garbage, that might be ok.
- // so we just fall through in that case.
- // HUMBUG
- if ( i == expAt ) {
- break parseNumber; // certainly bad
- }
- }
- //
- // We parsed everything we could.
- // If there are leftovers, then this is not good input!
- //
- if ( i < len &&
- ((i != len - 1) ||
- (in.charAt(i) != 'f' &&
- in.charAt(i) != 'F' &&
- in.charAt(i) != 'd' &&
- in.charAt(i) != 'D'))) {
- break parseNumber; // go throw exception
- }
- if(isZero) {
- return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
- }
- return new ASCIIToBinaryBuffer(isNegative, decExp, digits, nDigits);
- } catch ( StringIndexOutOfBoundsException e ){ }
- throw new NumberFormatException("For input string: \"" + in + "\"");
- }
-
- private static class HexFloatPattern {
- /**
- * Grammar is compatible with hexadecimal floating-point constants
- * described in section 6.4.4.2 of the C99 specification.
- */
- private static final Pattern VALUE = Pattern.compile(
- //1 234 56 7 8 9
- "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
- );
- }
-
- /**
- * Converts string s to a suitable floating decimal; uses the
- * double constructor and sets the roundDir variable appropriately
- * in case the value is later converted to a float.
- *
- * @param s The <code>String</code> to parse.
- */
- static ASCIIToBinaryConverter parseHexString(String s) {
- // Verify string is a member of the hexadecimal floating-point
- // string language.
- Matcher m = HexFloatPattern.VALUE.matcher(s);
- boolean validInput = m.matches();
- if (!validInput) {
- // Input does not match pattern
- throw new NumberFormatException("For input string: \"" + s + "\"");
- } else { // validInput
- //
- // We must isolate the sign, significand, and exponent
- // fields. The sign value is straightforward. Since
- // floating-point numbers are stored with a normalized
- // representation, the significand and exponent are
- // interrelated.
- //
- // After extracting the sign, we normalized the
- // significand as a hexadecimal value, calculating an
- // exponent adjust for any shifts made during
- // normalization. If the significand is zero, the
- // exponent doesn't need to be examined since the output
- // will be zero.
- //
- // Next the exponent in the input string is extracted.
- // Afterwards, the significand is normalized as a *binary*
- // value and the input value's normalized exponent can be
- // computed. The significand bits are copied into a
- // double significand; if the string has more logical bits
- // than can fit in a double, the extra bits affect the
- // round and sticky bits which are used to round the final
- // value.
- //
- // Extract significand sign
- String group1 = m.group(1);
- boolean isNegative = ((group1 != null) && group1.equals("-"));
-
- // Extract Significand magnitude
- //
- // Based on the form of the significand, calculate how the
- // binary exponent needs to be adjusted to create a
- // normalized//hexadecimal* floating-point number; that
- // is, a number where there is one nonzero hex digit to
- // the left of the (hexa)decimal point. Since we are
- // adjusting a binary, not hexadecimal exponent, the
- // exponent is adjusted by a multiple of 4.
- //
- // There are a number of significand scenarios to consider;
- // letters are used in indicate nonzero digits:
- //
- // 1. 000xxxx => x.xxx normalized
- // increase exponent by (number of x's - 1)*4
- //
- // 2. 000xxx.yyyy => x.xxyyyy normalized
- // increase exponent by (number of x's - 1)*4
- //
- // 3. .000yyy => y.yy normalized
- // decrease exponent by (number of zeros + 1)*4
- //
- // 4. 000.00000yyy => y.yy normalized
- // decrease exponent by (number of zeros to right of point + 1)*4
- //
- // If the significand is exactly zero, return a properly
- // signed zero.
- //
-
- String significandString = null;
- int signifLength = 0;
- int exponentAdjust = 0;
- {
- int leftDigits = 0; // number of meaningful digits to
- // left of "decimal" point
- // (leading zeros stripped)
- int rightDigits = 0; // number of digits to right of
- // "decimal" point; leading zeros
- // must always be accounted for
- //
- // The significand is made up of either
- //
- // 1. group 4 entirely (integer portion only)
- //
- // OR
- //
- // 2. the fractional portion from group 7 plus any
- // (optional) integer portions from group 6.
- //
- String group4;
- if ((group4 = m.group(4)) != null) { // Integer-only significand
- // Leading zeros never matter on the integer portion
- significandString = stripLeadingZeros(group4);
- leftDigits = significandString.length();
- } else {
- // Group 6 is the optional integer; leading zeros
- // never matter on the integer portion
- String group6 = stripLeadingZeros(m.group(6));
- leftDigits = group6.length();
-
- // fraction
- String group7 = m.group(7);
- rightDigits = group7.length();
-
- // Turn "integer.fraction" into "integer"+"fraction"
- significandString =
- ((group6 == null) ? "" : group6) + // is the null
- // check necessary?
- group7;
- }
-
- significandString = stripLeadingZeros(significandString);
- signifLength = significandString.length();
-
- //
- // Adjust exponent as described above
- //
- if (leftDigits >= 1) { // Cases 1 and 2
- exponentAdjust = 4 * (leftDigits - 1);
- } else { // Cases 3 and 4
- exponentAdjust = -4 * (rightDigits - signifLength + 1);
- }
-
- // If the significand is zero, the exponent doesn't
- // matter; return a properly signed zero.
-
- if (signifLength == 0) { // Only zeros in input
- return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
- }
- }
-
- // Extract Exponent
- //
- // Use an int to read in the exponent value; this should
- // provide more than sufficient range for non-contrived
- // inputs. If reading the exponent in as an int does
- // overflow, examine the sign of the exponent and
- // significand to determine what to do.
- //
- String group8 = m.group(8);
- boolean positiveExponent = (group8 == null) || group8.equals("+");
- long unsignedRawExponent;
- try {
- unsignedRawExponent = Integer.parseInt(m.group(9));
- }
- catch (NumberFormatException e) {
- // At this point, we know the exponent is
- // syntactically well-formed as a sequence of
- // digits. Therefore, if an NumberFormatException
- // is thrown, it must be due to overflowing int's
- // range. Also, at this point, we have already
- // checked for a zero significand. Thus the signs
- // of the exponent and significand determine the
- // final result:
- //
- // significand
- // + -
- // exponent + +infinity -infinity
- // - +0.0 -0.0
- return isNegative ?
- (positiveExponent ? A2BC_NEGATIVE_INFINITY : A2BC_NEGATIVE_ZERO)
- : (positiveExponent ? A2BC_POSITIVE_INFINITY : A2BC_POSITIVE_ZERO);
-
- }
-
- long rawExponent =
- (positiveExponent ? 1L : -1L) * // exponent sign
- unsignedRawExponent; // exponent magnitude
-
- // Calculate partially adjusted exponent
- long exponent = rawExponent + exponentAdjust;
-
- // Starting copying non-zero bits into proper position in
- // a long; copy explicit bit too; this will be masked
- // later for normal values.
-
- boolean round = false;
- boolean sticky = false;
- int nextShift = 0;
- long significand = 0L;
- // First iteration is different, since we only copy
- // from the leading significand bit; one more exponent
- // adjust will be needed...
-
- // IMPORTANT: make leadingDigit a long to avoid
- // surprising shift semantics!
- long leadingDigit = getHexDigit(significandString, 0);
-
- //
- // Left shift the leading digit (53 - (bit position of
- // leading 1 in digit)); this sets the top bit of the
- // significand to 1. The nextShift value is adjusted
- // to take into account the number of bit positions of
- // the leadingDigit actually used. Finally, the
- // exponent is adjusted to normalize the significand
- // as a binary value, not just a hex value.
- //
- if (leadingDigit == 1) {
- significand |= leadingDigit << 52;
- nextShift = 52 - 4;
- // exponent += 0
- } else if (leadingDigit <= 3) { // [2, 3]
- significand |= leadingDigit << 51;
- nextShift = 52 - 5;
- exponent += 1;
- } else if (leadingDigit <= 7) { // [4, 7]
- significand |= leadingDigit << 50;
- nextShift = 52 - 6;
- exponent += 2;
- } else if (leadingDigit <= 15) { // [8, f]
- significand |= leadingDigit << 49;
- nextShift = 52 - 7;
- exponent += 3;
- } else {
- throw new AssertionError("Result from digit conversion too large!");
- }
- // The preceding if-else could be replaced by a single
- // code block based on the high-order bit set in
- // leadingDigit. Given leadingOnePosition,
-
- // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
- // nextShift = 52 - (3 + leadingOnePosition);
- // exponent += (leadingOnePosition-1);
-
- //
- // Now the exponent variable is equal to the normalized
- // binary exponent. Code below will make representation
- // adjustments if the exponent is incremented after
- // rounding (includes overflows to infinity) or if the
- // result is subnormal.
- //
-
- // Copy digit into significand until the significand can't
- // hold another full hex digit or there are no more input
- // hex digits.
- int i = 0;
- for (i = 1;
- i < signifLength && nextShift >= 0;
- i++) {
- long currentDigit = getHexDigit(significandString, i);
- significand |= (currentDigit << nextShift);
- nextShift -= 4;
- }
-
- // After the above loop, the bulk of the string is copied.
- // Now, we must copy any partial hex digits into the
- // significand AND compute the round bit and start computing
- // sticky bit.
-
- if (i < signifLength) { // at least one hex input digit exists
- long currentDigit = getHexDigit(significandString, i);
-
- // from nextShift, figure out how many bits need
- // to be copied, if any
- switch (nextShift) { // must be negative
- case -1:
- // three bits need to be copied in; can
- // set round bit
- significand |= ((currentDigit & 0xEL) >> 1);
- round = (currentDigit & 0x1L) != 0L;
- break;
-
- case -2:
- // two bits need to be copied in; can
- // set round and start sticky
- significand |= ((currentDigit & 0xCL) >> 2);
- round = (currentDigit & 0x2L) != 0L;
- sticky = (currentDigit & 0x1L) != 0;
- break;
-
- case -3:
- // one bit needs to be copied in
- significand |= ((currentDigit & 0x8L) >> 3);
- // Now set round and start sticky, if possible
- round = (currentDigit & 0x4L) != 0L;
- sticky = (currentDigit & 0x3L) != 0;
- break;
-
- case -4:
- // all bits copied into significand; set
- // round and start sticky
- round = ((currentDigit & 0x8L) != 0); // is top bit set?
- // nonzeros in three low order bits?
- sticky = (currentDigit & 0x7L) != 0;
- break;
-
- default:
- throw new AssertionError("Unexpected shift distance remainder.");
- // break;
- }
-
- // Round is set; sticky might be set.
-
- // For the sticky bit, it suffices to check the
- // current digit and test for any nonzero digits in
- // the remaining unprocessed input.
- i++;
- while (i < signifLength && !sticky) {
- currentDigit = getHexDigit(significandString, i);
- sticky = sticky || (currentDigit != 0);
- i++;
- }
-
- }
- // else all of string was seen, round and sticky are
- // correct as false.
-
- // Float calculations
- int floatBits = isNegative ? FloatConsts.SIGN_BIT_MASK : 0;
- if (exponent >= FloatConsts.MIN_EXPONENT) {
- if (exponent > FloatConsts.MAX_EXPONENT) {
- // Float.POSITIVE_INFINITY
- floatBits |= FloatConsts.EXP_BIT_MASK;
- } else {
- int threshShift = DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH - 1;
- boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
- int iValue = (int) (significand >>> threshShift);
- if ((iValue & 3) != 1 || floatSticky) {
- iValue++;
- }
- floatBits |= (((((int) exponent) + (FloatConsts.EXP_BIAS - 1))) << SINGLE_EXP_SHIFT) + (iValue >> 1);
- }
- } else {
- if (exponent < FloatConsts.MIN_SUB_EXPONENT - 1) {
- // 0
- } else {
- // exponent == -127 ==> threshShift = 53 - 2 + (-149) - (-127) = 53 - 24
- int threshShift = (int) ((DoubleConsts.SIGNIFICAND_WIDTH - 2 + FloatConsts.MIN_SUB_EXPONENT) - exponent);
- assert threshShift >= DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH;
- assert threshShift < DoubleConsts.SIGNIFICAND_WIDTH;
- boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
- int iValue = (int) (significand >>> threshShift);
- if ((iValue & 3) != 1 || floatSticky) {
- iValue++;
- }
- floatBits |= iValue >> 1;
- }
- }
- float fValue = Float.intBitsToFloat(floatBits);
-
- // Check for overflow and update exponent accordingly.
- if (exponent > DoubleConsts.MAX_EXPONENT) { // Infinite result
- // overflow to properly signed infinity
- return isNegative ? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
- } else { // Finite return value
- if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result
- exponent >= DoubleConsts.MIN_EXPONENT) {
-
- // The result returned in this block cannot be a
- // zero or subnormal; however after the
- // significand is adjusted from rounding, we could
- // still overflow in infinity.
-
- // AND exponent bits into significand; if the
- // significand is incremented and overflows from
- // rounding, this combination will update the
- // exponent correctly, even in the case of
- // Double.MAX_VALUE overflowing to infinity.
-
- significand = ((( exponent +
- (long) DoubleConsts.EXP_BIAS) <<
- (DoubleConsts.SIGNIFICAND_WIDTH - 1))
- & DoubleConsts.EXP_BIT_MASK) |
- (DoubleConsts.SIGNIF_BIT_MASK & significand);
-
- } else { // Subnormal or zero
- // (exponent < DoubleConsts.MIN_EXPONENT)
-
- if (exponent < (DoubleConsts.MIN_SUB_EXPONENT - 1)) {
- // No way to round back to nonzero value
- // regardless of significand if the exponent is
- // less than -1075.
- return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
- } else { // -1075 <= exponent <= MIN_EXPONENT -1 = -1023
- //
- // Find bit position to round to; recompute
- // round and sticky bits, and shift
- // significand right appropriately.
- //
-
- sticky = sticky || round;
- round = false;
-
- // Number of bits of significand to preserve is
- // exponent - abs_min_exp +1
- // check:
- // -1075 +1074 + 1 = 0
- // -1023 +1074 + 1 = 52
-
- int bitsDiscarded = 53 -
- ((int) exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
- assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
-
- // What to do here:
- // First, isolate the new round bit
- round = (significand & (1L << (bitsDiscarded - 1))) != 0L;
- if (bitsDiscarded > 1) {
- // create mask to update sticky bits; low
- // order bitsDiscarded bits should be 1
- long mask = ~((~0L) << (bitsDiscarded - 1));
- sticky = sticky || ((significand & mask) != 0L);
- }
-
- // Now, discard the bits
- significand = significand >> bitsDiscarded;
-
- significand = ((((long) (DoubleConsts.MIN_EXPONENT - 1) + // subnorm exp.
- (long) DoubleConsts.EXP_BIAS) <<
- (DoubleConsts.SIGNIFICAND_WIDTH - 1))
- & DoubleConsts.EXP_BIT_MASK) |
- (DoubleConsts.SIGNIF_BIT_MASK & significand);
- }
- }
-
- // The significand variable now contains the currently
- // appropriate exponent bits too.
-
- //
- // Determine if significand should be incremented;
- // making this determination depends on the least
- // significant bit and the round and sticky bits.
- //
- // Round to nearest even rounding table, adapted from
- // table 4.7 in "Computer Arithmetic" by IsraelKoren.
- // The digit to the left of the "decimal" point is the
- // least significant bit, the digits to the right of
- // the point are the round and sticky bits
- //
- // Number Round(x)
- // x0.00 x0.
- // x0.01 x0.
- // x0.10 x0.
- // x0.11 x1. = x0. +1
- // x1.00 x1.
- // x1.01 x1.
- // x1.10 x1. + 1
- // x1.11 x1. + 1
- //
- boolean leastZero = ((significand & 1L) == 0L);
- if ((leastZero && round && sticky) ||
- ((!leastZero) && round)) {
- significand++;
- }
-
- double value = isNegative ?
- Double.longBitsToDouble(significand | DoubleConsts.SIGN_BIT_MASK) :
- Double.longBitsToDouble(significand );
-
- return new PreparedASCIIToBinaryBuffer(value, fValue);
- }
- }
- }
-
- /**
- * Returns <code>s</code> with any leading zeros removed.
- */
- static String stripLeadingZeros(String s) {
-// return s.replaceFirst("^0+", "");
- if(!s.isEmpty() && s.charAt(0)=='0') {
- for(int i=1; i<s.length(); i++) {
- if(s.charAt(i)!='0') {
- return s.substring(i);
- }
- }
- return "";
- }
- return s;
- }
-
- /**
- * Extracts a hexadecimal digit from position <code>position</code>
- * of string <code>s</code>.
- */
- static int getHexDigit(String s, int position) {
- int value = Character.digit(s.charAt(position), 16);
- if (value <= -1 || value >= 16) {
- throw new AssertionError("Unexpected failure of digit conversion of " +
- s.charAt(position));
- }
- return value;
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/FormattedFloatingDecimal.java Tue Dec 22 11:07:17 2015 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,349 +0,0 @@
-/*
- * 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
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.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') };
- }
- }
-}
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatMath.java Tue Dec 22 11:07:17 2015 +0800
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatMath.java Tue Dec 22 12:17:25 2015 +0000
@@ -24,8 +24,8 @@
*/
package sun.java2d.marlin;
-import sun.misc.DoubleConsts;
-import sun.misc.FloatConsts;
+import jdk.internal.math.DoubleConsts;
+import jdk.internal.math.FloatConsts;
/**
* Faster Math ceil / floor routines derived from StrictMath
--- a/jdk/test/java/util/Formatter/Basic-X.java.template Tue Dec 22 11:07:17 2015 +0800
+++ b/jdk/test/java/util/Formatter/Basic-X.java.template Tue Dec 22 12:17:25 2015 +0000
@@ -36,7 +36,7 @@
import java.text.DateFormatSymbols;
import java.util.*;
#if[double]
-import sun.misc.DoubleConsts;
+import jdk.internal.math.DoubleConsts;
#end[double]
import static java.util.Calendar.*;
--- a/jdk/test/java/util/Formatter/Basic.java Tue Dec 22 11:07:17 2015 +0800
+++ b/jdk/test/java/util/Formatter/Basic.java Tue Dec 22 12:17:25 2015 +0000
@@ -28,7 +28,7 @@
* 6344623 6369500 6534606 6282094 6286592 6476425 5063507 6469160 6476168
* 8059175
*
- * @modules java.base/sun.misc
+ * @modules java.base/jdk.internal.math
* @run shell/timeout=240 Basic.sh
*/
--- a/jdk/test/java/util/Formatter/BasicDouble.java Tue Dec 22 11:07:17 2015 +0800
+++ b/jdk/test/java/util/Formatter/BasicDouble.java Tue Dec 22 12:17:25 2015 +0000
@@ -36,7 +36,7 @@
import java.text.DateFormatSymbols;
import java.util.*;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.DoubleConsts;
import static java.util.Calendar.*;
@@ -1174,6 +1174,10 @@
+
+
+
+
//---------------------------------------------------------------------
// %f - float, double, Double, BigDecimal
//---------------------------------------------------------------------
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/internal/math/FloatingDecimal/OldFDBigIntForTest.java Tue Dec 22 12:17:25 2015 +0000
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//package jdk.internal.math;
+
+/*
+ * A really, really simple bigint package
+ * tailored to the needs of floating base conversion.
+ */
+class OldFDBigIntForTest {
+ int nWords; // number of words used
+ int data[]; // value: data[0] is least significant
+
+
+ public OldFDBigIntForTest( int v ){
+ nWords = 1;
+ data = new int[1];
+ data[0] = v;
+ }
+
+ public OldFDBigIntForTest( long v ){
+ data = new int[2];
+ data[0] = (int)v;
+ data[1] = (int)(v>>>32);
+ nWords = (data[1]==0) ? 1 : 2;
+ }
+
+ public OldFDBigIntForTest( OldFDBigIntForTest other ){
+ data = new int[nWords = other.nWords];
+ System.arraycopy( other.data, 0, data, 0, nWords );
+ }
+
+ private OldFDBigIntForTest( int [] d, int n ){
+ data = d;
+ nWords = n;
+ }
+
+ public OldFDBigIntForTest( long seed, char digit[], int nd0, int nd ){
+ int n= (nd+8)/9; // estimate size needed.
+ if ( n < 2 ) n = 2;
+ data = new int[n]; // allocate enough space
+ data[0] = (int)seed; // starting value
+ data[1] = (int)(seed>>>32);
+ nWords = (data[1]==0) ? 1 : 2;
+ int i = nd0;
+ int limit = nd-5; // slurp digits 5 at a time.
+ int v;
+ while ( i < limit ){
+ int ilim = i+5;
+ v = (int)digit[i++]-(int)'0';
+ while( i <ilim ){
+ v = 10*v + (int)digit[i++]-(int)'0';
+ }
+ multaddMe( 100000, v); // ... where 100000 is 10^5.
+ }
+ int factor = 1;
+ v = 0;
+ while ( i < nd ){
+ v = 10*v + (int)digit[i++]-(int)'0';
+ factor *= 10;
+ }
+ if ( factor != 1 ){
+ multaddMe( factor, v );
+ }
+ }
+
+ /*
+ * Left shift by c bits.
+ * Shifts this in place.
+ */
+ public void
+ lshiftMe( int c )throws IllegalArgumentException {
+ if ( c <= 0 ){
+ if ( c == 0 )
+ return; // silly.
+ else
+ throw new IllegalArgumentException("negative shift count");
+ }
+ int wordcount = c>>5;
+ int bitcount = c & 0x1f;
+ int anticount = 32-bitcount;
+ int t[] = data;
+ int s[] = data;
+ if ( nWords+wordcount+1 > t.length ){
+ // reallocate.
+ t = new int[ nWords+wordcount+1 ];
+ }
+ int target = nWords+wordcount;
+ int src = nWords-1;
+ if ( bitcount == 0 ){
+ // special hack, since an anticount of 32 won't go!
+ System.arraycopy( s, 0, t, wordcount, nWords );
+ target = wordcount-1;
+ } else {
+ t[target--] = s[src]>>>anticount;
+ while ( src >= 1 ){
+ t[target--] = (s[src]<<bitcount) | (s[--src]>>>anticount);
+ }
+ t[target--] = s[src]<<bitcount;
+ }
+ while( target >= 0 ){
+ t[target--] = 0;
+ }
+ data = t;
+ nWords += wordcount + 1;
+ // may have constructed high-order word of 0.
+ // if so, trim it
+ while ( nWords > 1 && data[nWords-1] == 0 )
+ nWords--;
+ }
+
+ /*
+ * normalize this number by shifting until
+ * the MSB of the number is at 0x08000000.
+ * This is in preparation for quoRemIteration, below.
+ * The idea is that, to make division easier, we want the
+ * divisor to be "normalized" -- usually this means shifting
+ * the MSB into the high words sign bit. But because we know that
+ * the quotient will be 0 < q < 10, we would like to arrange that
+ * the dividend not span up into another word of precision.
+ * (This needs to be explained more clearly!)
+ */
+ public int
+ normalizeMe() throws IllegalArgumentException {
+ int src;
+ int wordcount = 0;
+ int bitcount = 0;
+ int v = 0;
+ for ( src= nWords-1 ; src >= 0 && (v=data[src]) == 0 ; src--){
+ wordcount += 1;
+ }
+ if ( src < 0 ){
+ // oops. Value is zero. Cannot normalize it!
+ throw new IllegalArgumentException("zero value");
+ }
+ /*
+ * In most cases, we assume that wordcount is zero. This only
+ * makes sense, as we try not to maintain any high-order
+ * words full of zeros. In fact, if there are zeros, we will
+ * simply SHORTEN our number at this point. Watch closely...
+ */
+ nWords -= wordcount;
+ /*
+ * Compute how far left we have to shift v s.t. its highest-
+ * order bit is in the right place. Then call lshiftMe to
+ * do the work.
+ */
+ if ( (v & 0xf0000000) != 0 ){
+ // will have to shift up into the next word.
+ // too bad.
+ for( bitcount = 32 ; (v & 0xf0000000) != 0 ; bitcount-- )
+ v >>>= 1;
+ } else {
+ while ( v <= 0x000fffff ){
+ // hack: byte-at-a-time shifting
+ v <<= 8;
+ bitcount += 8;
+ }
+ while ( v <= 0x07ffffff ){
+ v <<= 1;
+ bitcount += 1;
+ }
+ }
+ if ( bitcount != 0 )
+ lshiftMe( bitcount );
+ return bitcount;
+ }
+
+ /*
+ * Multiply a OldFDBigIntForTest by an int.
+ * Result is a new OldFDBigIntForTest.
+ */
+ public OldFDBigIntForTest
+ mult( int iv ) {
+ long v = iv;
+ int r[];
+ long p;
+
+ // guess adequate size of r.
+ r = new int[ ( v * ((long)data[nWords-1]&0xffffffffL) > 0xfffffffL ) ? nWords+1 : nWords ];
+ p = 0L;
+ for( int i=0; i < nWords; i++ ) {
+ p += v * ((long)data[i]&0xffffffffL);
+ r[i] = (int)p;
+ p >>>= 32;
+ }
+ if ( p == 0L){
+ return new OldFDBigIntForTest( r, nWords );
+ } else {
+ r[nWords] = (int)p;
+ return new OldFDBigIntForTest( r, nWords+1 );
+ }
+ }
+
+ /*
+ * Multiply a OldFDBigIntForTest by an int and add another int.
+ * Result is computed in place.
+ * Hope it fits!
+ */
+ public void
+ multaddMe( int iv, int addend ) {
+ long v = iv;
+ long p;
+
+ // unroll 0th iteration, doing addition.
+ p = v * ((long)data[0]&0xffffffffL) + ((long)addend&0xffffffffL);
+ data[0] = (int)p;
+ p >>>= 32;
+ for( int i=1; i < nWords; i++ ) {
+ p += v * ((long)data[i]&0xffffffffL);
+ data[i] = (int)p;
+ p >>>= 32;
+ }
+ if ( p != 0L){
+ data[nWords] = (int)p; // will fail noisily if illegal!
+ nWords++;
+ }
+ }
+
+ /*
+ * Multiply a OldFDBigIntForTest by another OldFDBigIntForTest.
+ * Result is a new OldFDBigIntForTest.
+ */
+ public OldFDBigIntForTest
+ mult( OldFDBigIntForTest other ){
+ // crudely guess adequate size for r
+ int r[] = new int[ nWords + other.nWords ];
+ int i;
+ // I think I am promised zeros...
+
+ for( i = 0; i < this.nWords; i++ ){
+ long v = (long)this.data[i] & 0xffffffffL; // UNSIGNED CONVERSION
+ long p = 0L;
+ int j;
+ for( j = 0; j < other.nWords; j++ ){
+ p += ((long)r[i+j]&0xffffffffL) + v*((long)other.data[j]&0xffffffffL); // UNSIGNED CONVERSIONS ALL 'ROUND.
+ r[i+j] = (int)p;
+ p >>>= 32;
+ }
+ r[i+j] = (int)p;
+ }
+ // compute how much of r we actually needed for all that.
+ for ( i = r.length-1; i> 0; i--)
+ if ( r[i] != 0 )
+ break;
+ return new OldFDBigIntForTest( r, i+1 );
+ }
+
+ /*
+ * Add one OldFDBigIntForTest to another. Return a OldFDBigIntForTest
+ */
+ public OldFDBigIntForTest
+ add( OldFDBigIntForTest other ){
+ int i;
+ int a[], b[];
+ int n, m;
+ long c = 0L;
+ // arrange such that a.nWords >= b.nWords;
+ // n = a.nWords, m = b.nWords
+ if ( this.nWords >= other.nWords ){
+ a = this.data;
+ n = this.nWords;
+ b = other.data;
+ m = other.nWords;
+ } else {
+ a = other.data;
+ n = other.nWords;
+ b = this.data;
+ m = this.nWords;
+ }
+ int r[] = new int[ n ];
+ for ( i = 0; i < n; i++ ){
+ c += (long)a[i] & 0xffffffffL;
+ if ( i < m ){
+ c += (long)b[i] & 0xffffffffL;
+ }
+ r[i] = (int) c;
+ c >>= 32; // signed shift.
+ }
+ if ( c != 0L ){
+ // oops -- carry out -- need longer result.
+ int s[] = new int[ r.length+1 ];
+ System.arraycopy( r, 0, s, 0, r.length );
+ s[i++] = (int)c;
+ return new OldFDBigIntForTest( s, i );
+ }
+ return new OldFDBigIntForTest( r, i );
+ }
+
+ /*
+ * Subtract one OldFDBigIntForTest from another. Return a OldFDBigIntForTest
+ * Assert that the result is positive.
+ */
+ public OldFDBigIntForTest
+ sub( OldFDBigIntForTest other ){
+ int r[] = new int[ this.nWords ];
+ int i;
+ int n = this.nWords;
+ int m = other.nWords;
+ int nzeros = 0;
+ long c = 0L;
+ for ( i = 0; i < n; i++ ){
+ c += (long)this.data[i] & 0xffffffffL;
+ if ( i < m ){
+ c -= (long)other.data[i] & 0xffffffffL;
+ }
+ if ( ( r[i] = (int) c ) == 0 )
+ nzeros++;
+ else
+ nzeros = 0;
+ c >>= 32; // signed shift
+ }
+ assert c == 0L : c; // borrow out of subtract
+ assert dataInRangeIsZero(i, m, other); // negative result of subtract
+ return new OldFDBigIntForTest( r, n-nzeros );
+ }
+
+ private static boolean dataInRangeIsZero(int i, int m, OldFDBigIntForTest other) {
+ while ( i < m )
+ if (other.data[i++] != 0)
+ return false;
+ return true;
+ }
+
+ /*
+ * Compare OldFDBigIntForTest with another OldFDBigIntForTest. Return an integer
+ * >0: this > other
+ * 0: this == other
+ * <0: this < other
+ */
+ public int
+ cmp( OldFDBigIntForTest other ){
+ int i;
+ if ( this.nWords > other.nWords ){
+ // if any of my high-order words is non-zero,
+ // then the answer is evident
+ int j = other.nWords-1;
+ for ( i = this.nWords-1; i > j ; i-- )
+ if ( this.data[i] != 0 ) return 1;
+ }else if ( this.nWords < other.nWords ){
+ // if any of other's high-order words is non-zero,
+ // then the answer is evident
+ int j = this.nWords-1;
+ for ( i = other.nWords-1; i > j ; i-- )
+ if ( other.data[i] != 0 ) return -1;
+ } else{
+ i = this.nWords-1;
+ }
+ for ( ; i > 0 ; i-- )
+ if ( this.data[i] != other.data[i] )
+ break;
+ // careful! want unsigned compare!
+ // use brute force here.
+ int a = this.data[i];
+ int b = other.data[i];
+ if ( a < 0 ){
+ // a is really big, unsigned
+ if ( b < 0 ){
+ return a-b; // both big, negative
+ } else {
+ return 1; // b not big, answer is obvious;
+ }
+ } else {
+ // a is not really big
+ if ( b < 0 ) {
+ // but b is really big
+ return -1;
+ } else {
+ return a - b;
+ }
+ }
+ }
+
+ /*
+ * Compute
+ * q = (int)( this / S )
+ * this = 10 * ( this mod S )
+ * Return q.
+ * This is the iteration step of digit development for output.
+ * We assume that S has been normalized, as above, and that
+ * "this" has been lshift'ed accordingly.
+ * Also assume, of course, that the result, q, can be expressed
+ * as an integer, 0 <= q < 10.
+ */
+ public int
+ quoRemIteration( OldFDBigIntForTest S )throws IllegalArgumentException {
+ // ensure that this and S have the same number of
+ // digits. If S is properly normalized and q < 10 then
+ // this must be so.
+ if ( nWords != S.nWords ){
+ throw new IllegalArgumentException("disparate values");
+ }
+ // estimate q the obvious way. We will usually be
+ // right. If not, then we're only off by a little and
+ // will re-add.
+ int n = nWords-1;
+ long q = ((long)data[n]&0xffffffffL) / (long)S.data[n];
+ long diff = 0L;
+ for ( int i = 0; i <= n ; i++ ){
+ diff += ((long)data[i]&0xffffffffL) - q*((long)S.data[i]&0xffffffffL);
+ data[i] = (int)diff;
+ diff >>= 32; // N.B. SIGNED shift.
+ }
+ if ( diff != 0L ) {
+ // damn, damn, damn. q is too big.
+ // add S back in until this turns +. This should
+ // not be very many times!
+ long sum = 0L;
+ while ( sum == 0L ){
+ sum = 0L;
+ for ( int i = 0; i <= n; i++ ){
+ sum += ((long)data[i]&0xffffffffL) + ((long)S.data[i]&0xffffffffL);
+ data[i] = (int) sum;
+ sum >>= 32; // Signed or unsigned, answer is 0 or 1
+ }
+ /*
+ * Originally the following line read
+ * "if ( sum !=0 && sum != -1 )"
+ * but that would be wrong, because of the
+ * treatment of the two values as entirely unsigned,
+ * it would be impossible for a carry-out to be interpreted
+ * as -1 -- it would have to be a single-bit carry-out, or
+ * +1.
+ */
+ assert sum == 0 || sum == 1 : sum; // carry out of division correction
+ q -= 1;
+ }
+ }
+ // finally, we can multiply this by 10.
+ // it cannot overflow, right, as the high-order word has
+ // at least 4 high-order zeros!
+ long p = 0L;
+ for ( int i = 0; i <= n; i++ ){
+ p += 10*((long)data[i]&0xffffffffL);
+ data[i] = (int)p;
+ p >>= 32; // SIGNED shift.
+ }
+ assert p == 0L : p; // Carry out of *10
+ return (int)q;
+ }
+
+ public long
+ longValue(){
+ // if this can be represented as a long, return the value
+ assert this.nWords > 0 : this.nWords; // longValue confused
+
+ if (this.nWords == 1)
+ return ((long)data[0]&0xffffffffL);
+
+ assert dataInRangeIsZero(2, this.nWords, this); // value too big
+ assert data[1] >= 0; // value too big
+ return ((long)(data[1]) << 32) | ((long)data[0]&0xffffffffL);
+ }
+
+ public String
+ toString() {
+ StringBuffer r = new StringBuffer(30);
+ r.append('[');
+ int i = Math.min( nWords-1, data.length-1) ;
+ if ( nWords > data.length ){
+ r.append( "("+data.length+"<"+nWords+"!)" );
+ }
+ for( ; i> 0 ; i-- ){
+ r.append( Integer.toHexString( data[i] ) );
+ r.append(' ');
+ }
+ r.append( Integer.toHexString( data[0] ) );
+ r.append(']');
+ return new String( r );
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/internal/math/FloatingDecimal/OldFloatingDecimalForTest.java Tue Dec 22 12:17:25 2015 +0000
@@ -0,0 +1,2434 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//package jdk.internal.math;
+
+import java.util.regex.*;
+
+public class OldFloatingDecimalForTest{
+ boolean isExceptional;
+ boolean isNegative;
+ int decExponent;
+ char digits[];
+ int nDigits;
+ int bigIntExp;
+ int bigIntNBits;
+ boolean mustSetRoundDir = false;
+ boolean fromHex = false;
+ int roundDir = 0; // set by doubleValue
+
+ /*
+ * The fields below provides additional information about the result of
+ * the binary to decimal digits conversion done in dtoa() and roundup()
+ * methods. They are changed if needed by those two methods.
+ */
+
+ // True if the dtoa() binary to decimal conversion was exact.
+ boolean exactDecimalConversion = false;
+
+ // True if the result of the binary to decimal conversion was rounded-up
+ // at the end of the conversion process, i.e. roundUp() method was called.
+ boolean decimalDigitsRoundedUp = false;
+
+ private OldFloatingDecimalForTest( boolean negSign, int decExponent, char []digits, int n, boolean e )
+ {
+ isNegative = negSign;
+ isExceptional = e;
+ this.decExponent = decExponent;
+ this.digits = digits;
+ this.nDigits = n;
+ }
+
+ /*
+ * Constants of the implementation
+ * Most are IEEE-754 related.
+ * (There are more really boring constants at the end.)
+ */
+ static final long signMask = 0x8000000000000000L;
+ static final long expMask = 0x7ff0000000000000L;
+ static final long fractMask= ~(signMask|expMask);
+ static final int expShift = 52;
+ static final int expBias = 1023;
+ static final long fractHOB = ( 1L<<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 OldFDBigIntForTest b5p[];
+
+ private static synchronized OldFDBigIntForTest
+ big5pow( int p ){
+ assert p >= 0 : p; // negative power of 5
+ if ( b5p == null ){
+ b5p = new OldFDBigIntForTest[ p+1 ];
+ }else if (b5p.length <= p ){
+ OldFDBigIntForTest t[] = new OldFDBigIntForTest[ p+1 ];
+ System.arraycopy( b5p, 0, t, 0, b5p.length );
+ b5p = t;
+ }
+ if ( b5p[p] != null )
+ return b5p[p];
+ else if ( p < small5pow.length )
+ return b5p[p] = new OldFDBigIntForTest( small5pow[p] );
+ else if ( p < long5pow.length )
+ return b5p[p] = new OldFDBigIntForTest( long5pow[p] );
+ else {
+ // construct the value.
+ // recursively.
+ int q, r;
+ // in order to compute 5^p,
+ // compute its square root, 5^(p/2) and square.
+ // or, let q = p / 2, r = p -q, then
+ // 5^p = 5^(q+r) = 5^q * 5^r
+ q = p >> 1;
+ r = p - q;
+ OldFDBigIntForTest bigq = b5p[q];
+ if ( bigq == null )
+ bigq = big5pow ( q );
+ if ( r < small5pow.length ){
+ return (b5p[p] = bigq.mult( small5pow[r] ) );
+ }else{
+ OldFDBigIntForTest bigr = b5p[ r ];
+ if ( bigr == null )
+ bigr = big5pow( r );
+ return (b5p[p] = bigq.mult( bigr ) );
+ }
+ }
+ }
+
+ //
+ // a common operation
+ //
+ private static OldFDBigIntForTest
+ multPow52( OldFDBigIntForTest v, int p5, int p2 ){
+ if ( p5 != 0 ){
+ if ( p5 < small5pow.length ){
+ v = v.mult( small5pow[p5] );
+ } else {
+ v = v.mult( big5pow( p5 ) );
+ }
+ }
+ if ( p2 != 0 ){
+ v.lshiftMe( p2 );
+ }
+ return v;
+ }
+
+ //
+ // another common operation
+ //
+ private static OldFDBigIntForTest
+ constructPow52( int p5, int p2 ){
+ OldFDBigIntForTest v = new OldFDBigIntForTest( big5pow( p5 ) );
+ if ( p2 != 0 ){
+ v.lshiftMe( p2 );
+ }
+ return v;
+ }
+
+ /*
+ * Make a floating double into a OldFDBigIntForTest.
+ * This could also be structured as a OldFDBigIntForTest
+ * constructor, but we'd have to build a lot of knowledge
+ * about floating-point representation into it, and we don't want to.
+ *
+ * AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
+ * bigIntExp and bigIntNBits
+ *
+ */
+ private OldFDBigIntForTest
+ doubleToBigInt( double dval ){
+ long lbits = Double.doubleToLongBits( dval ) & ~signMask;
+ int binexp = (int)(lbits >>> expShift);
+ lbits &= fractMask;
+ if ( binexp > 0 ){
+ lbits |= fractHOB;
+ } else {
+ assert lbits != 0L : lbits; // doubleToBigInt(0.0)
+ binexp +=1;
+ while ( (lbits & fractHOB ) == 0L){
+ lbits <<= 1;
+ binexp -= 1;
+ }
+ }
+ binexp -= expBias;
+ int nbits = countBits( lbits );
+ /*
+ * We now know where the high-order 1 bit is,
+ * and we know how many there are.
+ */
+ int lowOrderZeros = expShift+1-nbits;
+ lbits >>>= lowOrderZeros;
+
+ bigIntExp = binexp+1-nbits;
+ bigIntNBits = nbits;
+ return new OldFDBigIntForTest( lbits );
+ }
+
+ /*
+ * Compute a number that is the ULP of the given value,
+ * for purposes of addition/subtraction. Generally easy.
+ * More difficult if subtracting and the argument
+ * is a normalized a power of 2, as the ULP changes at these points.
+ */
+ private static double ulp( double dval, boolean subtracting ){
+ long lbits = Double.doubleToLongBits( dval ) & ~signMask;
+ int binexp = (int)(lbits >>> expShift);
+ double ulpval;
+ if ( subtracting && ( binexp >= expShift ) && ((lbits&fractMask) == 0L) ){
+ // for subtraction from normalized, powers of 2,
+ // use next-smaller exponent
+ binexp -= 1;
+ }
+ if ( binexp > expShift ){
+ ulpval = Double.longBitsToDouble( ((long)(binexp-expShift))<<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);
+ decimalDigitsRoundedUp = true;
+ }
+
+ public boolean digitsRoundedUp() {
+ return decimalDigitsRoundedUp;
+ }
+
+ /*
+ * FIRST IMPORTANT CONSTRUCTOR: DOUBLE
+ */
+ public OldFloatingDecimalForTest( double d )
+ {
+ long dBits = Double.doubleToLongBits( d );
+ long fractBits;
+ int binExp;
+ int nSignificantBits;
+
+ // discover and delete sign
+ if ( (dBits&signMask) != 0 ){
+ isNegative = true;
+ dBits ^= signMask;
+ } else {
+ isNegative = false;
+ }
+ // Begin to unpack
+ // Discover obvious special cases of NaN and Infinity.
+ binExp = (int)( (dBits&expMask) >> expShift );
+ fractBits = dBits&fractMask;
+ if ( binExp == (int)(expMask>>expShift) ) {
+ isExceptional = true;
+ if ( fractBits == 0L ){
+ digits = infinity;
+ } else {
+ digits = notANumber;
+ isNegative = false; // NaN has no sign!
+ }
+ nDigits = digits.length;
+ return;
+ }
+ isExceptional = false;
+ // Finish unpacking
+ // Normalize denormalized numbers.
+ // Insert assumed high-order bit for normalized numbers.
+ // Subtract exponent bias.
+ if ( binExp == 0 ){
+ if ( fractBits == 0L ){
+ // not a denorm, just a 0!
+ decExponent = 0;
+ digits = zero;
+ nDigits = 1;
+ return;
+ }
+ while ( (fractBits&fractHOB) == 0L ){
+ fractBits <<= 1;
+ binExp -= 1;
+ }
+ nSignificantBits = expShift + binExp +1; // recall binExp is - shift count.
+ binExp += 1;
+ } else {
+ fractBits |= fractHOB;
+ nSignificantBits = expShift+1;
+ }
+ binExp -= expBias;
+ // call the routine that actually does all the hard work.
+ dtoa( binExp, fractBits, nSignificantBits );
+ }
+
+ /*
+ * SECOND IMPORTANT CONSTRUCTOR: SINGLE
+ */
+ public OldFloatingDecimalForTest( float f )
+ {
+ int fBits = Float.floatToIntBits( f );
+ int fractBits;
+ int binExp;
+ int nSignificantBits;
+
+ // discover and delete sign
+ if ( (fBits&singleSignMask) != 0 ){
+ isNegative = true;
+ fBits ^= singleSignMask;
+ } else {
+ isNegative = false;
+ }
+ // Begin to unpack
+ // Discover obvious special cases of NaN and Infinity.
+ binExp = (fBits&singleExpMask) >> singleExpShift;
+ fractBits = fBits&singleFractMask;
+ if ( binExp == (singleExpMask>>singleExpShift) ) {
+ isExceptional = true;
+ if ( fractBits == 0L ){
+ digits = infinity;
+ } else {
+ digits = notANumber;
+ isNegative = false; // NaN has no sign!
+ }
+ nDigits = digits.length;
+ return;
+ }
+ isExceptional = false;
+ // Finish unpacking
+ // Normalize denormalized numbers.
+ // Insert assumed high-order bit for normalized numbers.
+ // Subtract exponent bias.
+ if ( binExp == 0 ){
+ if ( fractBits == 0 ){
+ // not a denorm, just a 0!
+ decExponent = 0;
+ digits = zero;
+ nDigits = 1;
+ return;
+ }
+ while ( (fractBits&singleFractHOB) == 0 ){
+ fractBits <<= 1;
+ binExp -= 1;
+ }
+ nSignificantBits = singleExpShift + binExp +1; // recall binExp is - shift count.
+ binExp += 1;
+ } else {
+ fractBits |= singleFractHOB;
+ nSignificantBits = singleExpShift+1;
+ }
+ binExp -= singleExpBias;
+ // call the routine that actually does all the hard work.
+ dtoa( binExp, ((long)fractBits)<<(expShift-singleExpShift), nSignificantBits );
+ }
+
+ private void
+ dtoa( int binExp, long fractBits, int nSignificantBits )
+ {
+ int nFractBits; // number of significant bits of fractBits;
+ int nTinyBits; // number of these to the right of the point.
+ int decExp;
+
+ // Examine number. Determine if it is an easy case,
+ // which we can do pretty trivially using float/long conversion,
+ // or whether we must do real work.
+ nFractBits = countBits( fractBits );
+ nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
+ if ( binExp <= maxSmallBinExp && binExp >= minSmallBinExp ){
+ // Look more closely at the number to decide if,
+ // with scaling by 10^nTinyBits, the result will fit in
+ // a long.
+ if ( (nTinyBits < long5pow.length) && ((nFractBits + n5bits[nTinyBits]) < 64 ) ){
+ /*
+ * We can do this:
+ * take the fraction bits, which are normalized.
+ * (a) nTinyBits == 0: Shift left or right appropriately
+ * to align the binary point at the extreme right, i.e.
+ * where a long int point is expected to be. The integer
+ * result is easily converted to a string.
+ * (b) nTinyBits > 0: Shift right by expShift-nFractBits,
+ * which effectively converts to long and scales by
+ * 2^nTinyBits. Then multiply by 5^nTinyBits to
+ * complete the scaling. We know this won't overflow
+ * because we just counted the number of bits necessary
+ * in the result. The integer you get from this can
+ * then be converted to a string pretty easily.
+ */
+ long halfULP;
+ if ( nTinyBits == 0 ) {
+ if ( binExp > nSignificantBits ){
+ halfULP = 1L << ( binExp-nSignificantBits-1);
+ } else {
+ halfULP = 0L;
+ }
+ if ( binExp >= expShift ){
+ fractBits <<= (binExp-expShift);
+ } else {
+ fractBits >>>= (expShift-binExp) ;
+ }
+ developLongDigits( 0, fractBits, halfULP );
+ return;
+ }
+ /*
+ * The following causes excess digits to be printed
+ * out in the single-float case. Our manipulation of
+ * halfULP here is apparently not correct. If we
+ * better understand how this works, perhaps we can
+ * use this special case again. But for the time being,
+ * we do not.
+ * else {
+ * fractBits >>>= expShift+1-nFractBits;
+ * fractBits *= long5pow[ nTinyBits ];
+ * halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
+ * developLongDigits( -nTinyBits, fractBits, halfULP );
+ * return;
+ * }
+ */
+ }
+ }
+ /*
+ * This is the hard case. We are going to compute large positive
+ * integers B and S and integer decExp, s.t.
+ * d = ( B / S ) * 10^decExp
+ * 1 <= B / S < 10
+ * Obvious choices are:
+ * decExp = floor( log10(d) )
+ * B = d * 2^nTinyBits * 10^max( 0, -decExp )
+ * S = 10^max( 0, decExp) * 2^nTinyBits
+ * (noting that nTinyBits has already been forced to non-negative)
+ * I am also going to compute a large positive integer
+ * M = (1/2^nSignificantBits) * 2^nTinyBits * 10^max( 0, -decExp )
+ * i.e. M is (1/2) of the ULP of d, scaled like B.
+ * When we iterate through dividing B/S and picking off the
+ * quotient bits, we will know when to stop when the remainder
+ * is <= M.
+ *
+ * We keep track of powers of 2 and powers of 5.
+ */
+
+ /*
+ * Estimate decimal exponent. (If it is small-ish,
+ * we could double-check.)
+ *
+ * First, scale the mantissa bits such that 1 <= d2 < 2.
+ * We are then going to estimate
+ * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5)
+ * and so we can estimate
+ * log10(d) ~=~ log10(d2) + binExp * log10(2)
+ * take the floor and call it decExp.
+ * FIXME -- use more precise constants here. It costs no more.
+ */
+ double d2 = Double.longBitsToDouble(
+ expOne | ( fractBits &~ fractHOB ) );
+ decExp = (int)Math.floor(
+ (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981 );
+ int B2, B5; // powers of 2 and powers of 5, respectively, in B
+ int S2, S5; // powers of 2 and powers of 5, respectively, in S
+ int M2, M5; // powers of 2 and powers of 5, respectively, in M
+ int Bbits; // binary digits needed to represent B, approx.
+ int tenSbits; // binary digits needed to represent 10*S, approx.
+ OldFDBigIntForTest Sval, Bval, Mval;
+
+ B5 = Math.max( 0, -decExp );
+ B2 = B5 + nTinyBits + binExp;
+
+ S5 = Math.max( 0, decExp );
+ S2 = S5 + nTinyBits;
+
+ M5 = B5;
+ M2 = B2 - nSignificantBits;
+
+ /*
+ * the long integer fractBits contains the (nFractBits) interesting
+ * bits from the mantissa of d ( hidden 1 added if necessary) followed
+ * by (expShift+1-nFractBits) zeros. In the interest of compactness,
+ * I will shift out those zeros before turning fractBits into a
+ * OldFDBigIntForTest. The resulting whole number will be
+ * d * 2^(nFractBits-1-binExp).
+ */
+ fractBits >>>= (expShift+1-nFractBits);
+ B2 -= nFractBits-1;
+ int common2factor = Math.min( B2, S2 );
+ B2 -= common2factor;
+ S2 -= common2factor;
+ M2 -= common2factor;
+
+ /*
+ * HACK!! For exact powers of two, the next smallest number
+ * is only half as far away as we think (because the meaning of
+ * ULP changes at power-of-two bounds) for this reason, we
+ * hack M2. Hope this works.
+ */
+ if ( nFractBits == 1 )
+ M2 -= 1;
+
+ if ( M2 < 0 ){
+ // oops.
+ // since we cannot scale M down far enough,
+ // we must scale the other values up.
+ B2 -= M2;
+ S2 -= M2;
+ M2 = 0;
+ }
+ /*
+ * Construct, Scale, iterate.
+ * Some day, we'll write a stopping test that takes
+ * account of the asymmetry of the spacing of floating-point
+ * numbers below perfect powers of 2
+ * 26 Sept 96 is not that day.
+ * So we use a symmetric test.
+ */
+ char digits[] = this.digits = new char[18];
+ int ndigit = 0;
+ boolean low, high;
+ long lowDigitDifference;
+ int q;
+
+ /*
+ * Detect the special cases where all the numbers we are about
+ * to compute will fit in int or long integers.
+ * In these cases, we will avoid doing OldFDBigIntForTest arithmetic.
+ * We use the same algorithms, except that we "normalize"
+ * our OldFDBigIntForTests before iterating. This is to make division easier,
+ * as it makes our fist guess (quotient of high-order words)
+ * more accurate!
+ *
+ * Some day, we'll write a stopping test that takes
+ * account of the asymmetry of the spacing of floating-point
+ * numbers below perfect powers of 2
+ * 26 Sept 96 is not that day.
+ * So we use a symmetric test.
+ */
+ Bbits = nFractBits + B2 + (( B5 < n5bits.length )? n5bits[B5] : ( B5*3 ));
+ tenSbits = S2+1 + (( (S5+1) < n5bits.length )? n5bits[(S5+1)] : ( (S5+1)*3 ));
+ if ( Bbits < 64 && tenSbits < 64){
+ if ( Bbits < 32 && tenSbits < 32){
+ // wa-hoo! They're all ints!
+ int b = ((int)fractBits * small5pow[B5] ) << B2;
+ int s = small5pow[S5] << S2;
+ int m = small5pow[M5] << M2;
+ int tens = s * 10;
+ /*
+ * Unroll the first iteration. If our decExp estimate
+ * was too high, our first quotient will be zero. In this
+ * case, we discard it and decrement decExp.
+ */
+ ndigit = 0;
+ q = b / s;
+ b = 10 * ( b % s );
+ m *= 10;
+ low = (b < m );
+ high = (b+m > tens );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ /*
+ * HACK! Java spec sez that we always have at least
+ * one digit after the . in either F- or E-form output.
+ * Thus we will need more than one digit if we're using
+ * E-form
+ */
+ if ( decExp < -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = b / s;
+ b = 10 * ( b % s );
+ m *= 10;
+ assert q < 10 : q; // excessively large digit
+ if ( m > 0L ){
+ low = (b < m );
+ high = (b+m > tens );
+ } else {
+ // hack -- m might overflow!
+ // in this case, it is certainly > b,
+ // which won't
+ // and b+m > tens, too, since that has overflowed
+ // either!
+ low = true;
+ high = true;
+ }
+ digits[ndigit++] = (char)('0' + q);
+ }
+ lowDigitDifference = (b<<1) - tens;
+ exactDecimalConversion = (b == 0);
+ } else {
+ // still good! they're all longs!
+ long b = (fractBits * long5pow[B5] ) << B2;
+ long s = long5pow[S5] << S2;
+ long m = long5pow[M5] << M2;
+ long tens = s * 10L;
+ /*
+ * Unroll the first iteration. If our decExp estimate
+ * was too high, our first quotient will be zero. In this
+ * case, we discard it and decrement decExp.
+ */
+ ndigit = 0;
+ q = (int) ( b / s );
+ b = 10L * ( b % s );
+ m *= 10L;
+ low = (b < m );
+ high = (b+m > tens );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ /*
+ * HACK! Java spec sez that we always have at least
+ * one digit after the . in either F- or E-form output.
+ * Thus we will need more than one digit if we're using
+ * E-form
+ */
+ if ( decExp < -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = (int) ( b / s );
+ b = 10 * ( b % s );
+ m *= 10;
+ assert q < 10 : q; // excessively large digit
+ if ( m > 0L ){
+ low = (b < m );
+ high = (b+m > tens );
+ } else {
+ // hack -- m might overflow!
+ // in this case, it is certainly > b,
+ // which won't
+ // and b+m > tens, too, since that has overflowed
+ // either!
+ low = true;
+ high = true;
+ }
+ digits[ndigit++] = (char)('0' + q);
+ }
+ lowDigitDifference = (b<<1) - tens;
+ exactDecimalConversion = (b == 0);
+ }
+ } else {
+ OldFDBigIntForTest ZeroVal = new OldFDBigIntForTest(0);
+ OldFDBigIntForTest tenSval;
+ int shiftBias;
+
+ /*
+ * We really must do OldFDBigIntForTest arithmetic.
+ * Fist, construct our OldFDBigIntForTest initial values.
+ */
+ Bval = multPow52( new OldFDBigIntForTest( fractBits ), B5, B2 );
+ Sval = constructPow52( S5, S2 );
+ Mval = constructPow52( M5, M2 );
+
+
+ // normalize so that division works better
+ Bval.lshiftMe( shiftBias = Sval.normalizeMe() );
+ Mval.lshiftMe( shiftBias );
+ tenSval = Sval.mult( 10 );
+ /*
+ * Unroll the first iteration. If our decExp estimate
+ * was too high, our first quotient will be zero. In this
+ * case, we discard it and decrement decExp.
+ */
+ ndigit = 0;
+ q = Bval.quoRemIteration( Sval );
+ Mval = Mval.mult( 10 );
+ low = (Bval.cmp( Mval ) < 0);
+ high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ /*
+ * HACK! Java spec sez that we always have at least
+ * one digit after the . in either F- or E-form output.
+ * Thus we will need more than one digit if we're using
+ * E-form
+ */
+ if ( decExp < -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = Bval.quoRemIteration( Sval );
+ Mval = Mval.mult( 10 );
+ assert q < 10 : q; // excessively large digit
+ low = (Bval.cmp( Mval ) < 0);
+ high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
+ digits[ndigit++] = (char)('0' + q);
+ }
+ if ( high && low ){
+ Bval.lshiftMe(1);
+ lowDigitDifference = Bval.cmp(tenSval);
+ } else {
+ lowDigitDifference = 0L; // this here only for flow analysis!
+ }
+ exactDecimalConversion = (Bval.cmp( ZeroVal ) == 0);
+ }
+ this.decExponent = decExp+1;
+ this.digits = digits;
+ this.nDigits = ndigit;
+ /*
+ * Last digit gets rounded based on stopping condition.
+ */
+ if ( high ){
+ if ( low ){
+ if ( lowDigitDifference == 0L ){
+ // it's a tie!
+ // choose based on which digits we like.
+ if ( (digits[nDigits-1]&1) != 0 ) roundup();
+ } else if ( lowDigitDifference > 0 ){
+ roundup();
+ }
+ } else {
+ roundup();
+ }
+ }
+ }
+
+ public boolean decimalDigitsExact() {
+ return exactDecimalConversion;
+ }
+
+ public String
+ toString(){
+ // most brain-dead version
+ StringBuffer result = new StringBuffer( nDigits+8 );
+ if ( isNegative ){ result.append( '-' ); }
+ if ( isExceptional ){
+ result.append( digits, 0, nDigits );
+ } else {
+ result.append( "0.");
+ result.append( digits, 0, nDigits );
+ result.append('e');
+ result.append( decExponent );
+ }
+ return new String(result);
+ }
+
+ public String toJavaFormatString() {
+ char result[] = perThreadBuffer.get();
+ int i = getChars(result);
+ return new String(result, 0, i);
+ }
+
+ private int getChars(char[] result) {
+ assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
+ int i = 0;
+ if (isNegative) { result[0] = '-'; i = 1; }
+ if (isExceptional) {
+ System.arraycopy(digits, 0, result, i, nDigits);
+ i += nDigits;
+ } else {
+ if (decExponent > 0 && decExponent < 8) {
+ // print digits.digits.
+ int charLength = Math.min(nDigits, decExponent);
+ System.arraycopy(digits, 0, result, i, charLength);
+ i += charLength;
+ if (charLength < decExponent) {
+ charLength = decExponent-charLength;
+ System.arraycopy(zero, 0, result, i, charLength);
+ i += charLength;
+ result[i++] = '.';
+ result[i++] = '0';
+ } else {
+ result[i++] = '.';
+ if (charLength < nDigits) {
+ int t = nDigits - charLength;
+ System.arraycopy(digits, charLength, result, i, t);
+ i += t;
+ } else {
+ result[i++] = '0';
+ }
+ }
+ } else if (decExponent <=0 && decExponent > -3) {
+ result[i++] = '0';
+ result[i++] = '.';
+ if (decExponent != 0) {
+ System.arraycopy(zero, 0, result, i, -decExponent);
+ i -= decExponent;
+ }
+ System.arraycopy(digits, 0, result, i, nDigits);
+ i += nDigits;
+ } else {
+ result[i++] = digits[0];
+ result[i++] = '.';
+ if (nDigits > 1) {
+ System.arraycopy(digits, 1, result, i, nDigits-1);
+ i += nDigits-1;
+ } else {
+ result[i++] = '0';
+ }
+ result[i++] = 'E';
+ int e;
+ if (decExponent <= 0) {
+ result[i++] = '-';
+ e = -decExponent+1;
+ } else {
+ e = decExponent-1;
+ }
+ // decExponent has 1, 2, or 3, digits
+ if (e <= 9) {
+ result[i++] = (char)(e+'0');
+ } else if (e <= 99) {
+ result[i++] = (char)(e/10 +'0');
+ result[i++] = (char)(e%10 + '0');
+ } else {
+ result[i++] = (char)(e/100+'0');
+ e %= 100;
+ result[i++] = (char)(e/10+'0');
+ result[i++] = (char)(e%10 + '0');
+ }
+ }
+ }
+ return i;
+ }
+
+ // Per-thread buffer for string/stringbuffer conversion
+ private static ThreadLocal<char[]> perThreadBuffer = new ThreadLocal<char[]>() {
+ protected synchronized char[] initialValue() {
+ return new char[26];
+ }
+ };
+
+ public void appendTo(Appendable buf) {
+ char result[] = perThreadBuffer.get();
+ int i = getChars(result);
+ if (buf instanceof StringBuilder)
+ ((StringBuilder) buf).append(result, 0, i);
+ else if (buf instanceof StringBuffer)
+ ((StringBuffer) buf).append(result, 0, i);
+ else
+ assert false;
+ }
+
+ @SuppressWarnings("fallthrough")
+ public static OldFloatingDecimalForTest
+ readJavaFormatString( String in ) throws NumberFormatException {
+ boolean isNegative = false;
+ boolean signSeen = false;
+ int decExp;
+ char c;
+
+ parseNumber:
+ try{
+ in = in.trim(); // don't fool around with white space.
+ // throws NullPointerException if null
+ int l = in.length();
+ if ( l == 0 ) throw new NumberFormatException("empty String");
+ int i = 0;
+ switch ( c = in.charAt( i ) ){
+ case '-':
+ isNegative = true;
+ //FALLTHROUGH
+ case '+':
+ i++;
+ signSeen = true;
+ }
+
+ // Check for NaN and Infinity strings
+ c = in.charAt(i);
+ if(c == 'N' || c == 'I') { // possible NaN or infinity
+ boolean potentialNaN = false;
+ char targetChars[] = null; // char array of "NaN" or "Infinity"
+
+ if(c == 'N') {
+ targetChars = notANumber;
+ potentialNaN = true;
+ } else {
+ targetChars = infinity;
+ }
+
+ // compare Input string to "NaN" or "Infinity"
+ int j = 0;
+ while(i < l && j < targetChars.length) {
+ if(in.charAt(i) == targetChars[j]) {
+ i++; j++;
+ }
+ else // something is amiss, throw exception
+ break parseNumber;
+ }
+
+ // For the candidate string to be a NaN or infinity,
+ // all characters in input string and target char[]
+ // must be matched ==> j must equal targetChars.length
+ // and i must equal l
+ if( (j == targetChars.length) && (i == l) ) { // return NaN or infinity
+ return (potentialNaN ? new OldFloatingDecimalForTest(Double.NaN) // NaN has no sign
+ : new OldFloatingDecimalForTest(isNegative?
+ Double.NEGATIVE_INFINITY:
+ Double.POSITIVE_INFINITY)) ;
+ }
+ else { // something went wrong, throw exception
+ break parseNumber;
+ }
+
+ } else if (c == '0') { // check for hexadecimal floating-point number
+ if (l > i+1 ) {
+ char ch = in.charAt(i+1);
+ if (ch == 'x' || ch == 'X' ) // possible hex string
+ return parseHexString(in);
+ }
+ } // look for and process decimal floating-point string
+
+ char[] digits = new char[ l ];
+ int nDigits= 0;
+ boolean decSeen = false;
+ int decPt = 0;
+ int nLeadZero = 0;
+ int nTrailZero= 0;
+ digitLoop:
+ while ( i < l ){
+ switch ( c = in.charAt( i ) ){
+ case '0':
+ if ( nDigits > 0 ){
+ nTrailZero += 1;
+ } else {
+ nLeadZero += 1;
+ }
+ break; // out of switch.
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ while ( nTrailZero > 0 ){
+ digits[nDigits++] = '0';
+ nTrailZero -= 1;
+ }
+ digits[nDigits++] = c;
+ break; // out of switch.
+ case '.':
+ if ( decSeen ){
+ // already saw one ., this is the 2nd.
+ throw new NumberFormatException("multiple points");
+ }
+ decPt = i;
+ if ( signSeen ){
+ decPt -= 1;
+ }
+ decSeen = true;
+ break; // out of switch.
+ default:
+ break digitLoop;
+ }
+ i++;
+ }
+ /*
+ * At this point, we've scanned all the digits and decimal
+ * point we're going to see. Trim off leading and trailing
+ * zeros, which will just confuse us later, and adjust
+ * our initial decimal exponent accordingly.
+ * To review:
+ * we have seen i total characters.
+ * nLeadZero of them were zeros before any other digits.
+ * nTrailZero of them were zeros after any other digits.
+ * if ( decSeen ), then a . was seen after decPt characters
+ * ( including leading zeros which have been discarded )
+ * nDigits characters were neither lead nor trailing
+ * zeros, nor point
+ */
+ /*
+ * special hack: if we saw no non-zero digits, then the
+ * answer is zero!
+ * Unfortunately, we feel honor-bound to keep parsing!
+ */
+ if ( nDigits == 0 ){
+ digits = zero;
+ nDigits = 1;
+ if ( nLeadZero == 0 ){
+ // we saw NO DIGITS AT ALL,
+ // not even a crummy 0!
+ // this is not allowed.
+ break parseNumber; // go throw exception
+ }
+
+ }
+
+ /* Our initial exponent is decPt, adjusted by the number of
+ * discarded zeros. Or, if there was no decPt,
+ * then its just nDigits adjusted by discarded trailing zeros.
+ */
+ if ( decSeen ){
+ decExp = decPt - nLeadZero;
+ } else {
+ decExp = nDigits+nTrailZero;
+ }
+
+ /*
+ * Look for 'e' or 'E' and an optionally signed integer.
+ */
+ if ( (i < l) && (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
+ int expSign = 1;
+ int expVal = 0;
+ int reallyBig = Integer.MAX_VALUE / 10;
+ boolean expOverflow = false;
+ switch( in.charAt(++i) ){
+ case '-':
+ expSign = -1;
+ //FALLTHROUGH
+ case '+':
+ i++;
+ }
+ int expAt = i;
+ expLoop:
+ while ( i < l ){
+ if ( expVal >= reallyBig ){
+ // the next character will cause integer
+ // overflow.
+ expOverflow = true;
+ }
+ switch ( c = in.charAt(i++) ){
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ expVal = expVal*10 + ( (int)c - (int)'0' );
+ continue;
+ default:
+ i--; // back up.
+ break expLoop; // stop parsing exponent.
+ }
+ }
+ int expLimit = bigDecimalExponent+nDigits+nTrailZero;
+ if ( expOverflow || ( expVal > expLimit ) ){
+ //
+ // The intent here is to end up with
+ // infinity or zero, as appropriate.
+ // The reason for yielding such a small decExponent,
+ // rather than something intuitive such as
+ // expSign*Integer.MAX_VALUE, is that this value
+ // is subject to further manipulation in
+ // doubleValue() and floatValue(), and I don't want
+ // it to be able to cause overflow there!
+ // (The only way we can get into trouble here is for
+ // really outrageous nDigits+nTrailZero, such as 2 billion. )
+ //
+ decExp = expSign*expLimit;
+ } else {
+ // this should not overflow, since we tested
+ // for expVal > (MAX+N), where N >= abs(decExp)
+ decExp = decExp + expSign*expVal;
+ }
+
+ // if we saw something not a digit ( or end of string )
+ // after the [Ee][+-], without seeing any digits at all
+ // this is certainly an error. If we saw some digits,
+ // but then some trailing garbage, that might be ok.
+ // so we just fall through in that case.
+ // HUMBUG
+ if ( i == expAt )
+ break parseNumber; // certainly bad
+ }
+ /*
+ * We parsed everything we could.
+ * If there are leftovers, then this is not good input!
+ */
+ if ( i < l &&
+ ((i != l - 1) ||
+ (in.charAt(i) != 'f' &&
+ in.charAt(i) != 'F' &&
+ in.charAt(i) != 'd' &&
+ in.charAt(i) != 'D'))) {
+ break parseNumber; // go throw exception
+ }
+
+ return new OldFloatingDecimalForTest( isNegative, decExp, digits, nDigits, false );
+ } catch ( StringIndexOutOfBoundsException e ){ }
+ throw new NumberFormatException("For input string: \"" + in + "\"");
+ }
+
+ /*
+ * Take a FloatingDecimal, which we presumably just scanned in,
+ * and find out what its value is, as a double.
+ *
+ * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
+ * ROUNDING DIRECTION in case the result is really destined
+ * for a single-precision float.
+ */
+
+ public strictfp double doubleValue(){
+ int kDigits = Math.min( nDigits, maxDecimalDigits+1 );
+ long lValue;
+ double dValue;
+ double rValue, tValue;
+
+ // First, check for NaN and Infinity values
+ if(digits == infinity || digits == notANumber) {
+ if(digits == notANumber)
+ return Double.NaN;
+ else
+ return (isNegative?Double.NEGATIVE_INFINITY:Double.POSITIVE_INFINITY);
+ }
+ else {
+ if (mustSetRoundDir) {
+ roundDir = 0;
+ }
+ /*
+ * convert the lead kDigits to a long integer.
+ */
+ // (special performance hack: start to do it using int)
+ int iValue = (int)digits[0]-(int)'0';
+ int iDigits = Math.min( kDigits, intDecimalDigits );
+ for ( int i=1; i < iDigits; i++ ){
+ iValue = iValue*10 + (int)digits[i]-(int)'0';
+ }
+ lValue = (long)iValue;
+ for ( int i=iDigits; i < kDigits; i++ ){
+ lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
+ }
+ dValue = (double)lValue;
+ int exp = decExponent-kDigits;
+ /*
+ * lValue now contains a long integer with the value of
+ * the first kDigits digits of the number.
+ * dValue contains the (double) of the same.
+ */
+
+ if ( nDigits <= maxDecimalDigits ){
+ /*
+ * possibly an easy case.
+ * We know that the digits can be represented
+ * exactly. And if the exponent isn't too outrageous,
+ * the whole thing can be done with one operation,
+ * thus one rounding error.
+ * Note that all our constructors trim all leading and
+ * trailing zeros, so simple values (including zero)
+ * will always end up here
+ */
+ if (exp == 0 || dValue == 0.0)
+ return (isNegative)? -dValue : dValue; // small floating integer
+ else if ( exp >= 0 ){
+ if ( exp <= maxSmallTen ){
+ /*
+ * Can get the answer with one operation,
+ * thus one roundoff.
+ */
+ rValue = dValue * small10pow[exp];
+ if ( mustSetRoundDir ){
+ tValue = rValue / small10pow[exp];
+ roundDir = ( tValue == dValue ) ? 0
+ :( tValue < dValue ) ? 1
+ : -1;
+ }
+ return (isNegative)? -rValue : rValue;
+ }
+ int slop = maxDecimalDigits - kDigits;
+ if ( exp <= maxSmallTen+slop ){
+ /*
+ * We can multiply dValue by 10^(slop)
+ * and it is still "small" and exact.
+ * Then we can multiply by 10^(exp-slop)
+ * with one rounding.
+ */
+ dValue *= small10pow[slop];
+ rValue = dValue * small10pow[exp-slop];
+
+ if ( mustSetRoundDir ){
+ tValue = rValue / small10pow[exp-slop];
+ roundDir = ( tValue == dValue ) ? 0
+ :( tValue < dValue ) ? 1
+ : -1;
+ }
+ return (isNegative)? -rValue : rValue;
+ }
+ /*
+ * Else we have a hard case with a positive exp.
+ */
+ } else {
+ if ( exp >= -maxSmallTen ){
+ /*
+ * Can get the answer in one division.
+ */
+ rValue = dValue / small10pow[-exp];
+ tValue = rValue * small10pow[-exp];
+ if ( mustSetRoundDir ){
+ roundDir = ( tValue == dValue ) ? 0
+ :( tValue < dValue ) ? 1
+ : -1;
+ }
+ return (isNegative)? -rValue : rValue;
+ }
+ /*
+ * Else we have a hard case with a negative exp.
+ */
+ }
+ }
+
+ /*
+ * Harder cases:
+ * The sum of digits plus exponent is greater than
+ * what we think we can do with one error.
+ *
+ * Start by approximating the right answer by,
+ * naively, scaling by powers of 10.
+ */
+ if ( exp > 0 ){
+ if ( decExponent > maxDecimalExponent+1 ){
+ /*
+ * Lets face it. This is going to be
+ * Infinity. Cut to the chase.
+ */
+ return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ if ( (exp&15) != 0 ){
+ dValue *= small10pow[exp&15];
+ }
+ if ( (exp>>=4) != 0 ){
+ int j;
+ for( j = 0; exp > 1; j++, exp>>=1 ){
+ if ( (exp&1)!=0)
+ dValue *= big10pow[j];
+ }
+ /*
+ * The reason for the weird exp > 1 condition
+ * in the above loop was so that the last multiply
+ * would get unrolled. We handle it here.
+ * It could overflow.
+ */
+ double t = dValue * big10pow[j];
+ if ( Double.isInfinite( t ) ){
+ /*
+ * It did overflow.
+ * Look more closely at the result.
+ * If the exponent is just one too large,
+ * then use the maximum finite as our estimate
+ * value. Else call the result infinity
+ * and punt it.
+ * ( I presume this could happen because
+ * rounding forces the result here to be
+ * an ULP or two larger than
+ * Double.MAX_VALUE ).
+ */
+ t = dValue / 2.0;
+ t *= big10pow[j];
+ if ( Double.isInfinite( t ) ){
+ return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ t = Double.MAX_VALUE;
+ }
+ dValue = t;
+ }
+ } else if ( exp < 0 ){
+ exp = -exp;
+ if ( decExponent < minDecimalExponent-1 ){
+ /*
+ * Lets face it. This is going to be
+ * zero. Cut to the chase.
+ */
+ return (isNegative)? -0.0 : 0.0;
+ }
+ if ( (exp&15) != 0 ){
+ dValue /= small10pow[exp&15];
+ }
+ if ( (exp>>=4) != 0 ){
+ int j;
+ for( j = 0; exp > 1; j++, exp>>=1 ){
+ if ( (exp&1)!=0)
+ dValue *= tiny10pow[j];
+ }
+ /*
+ * The reason for the weird exp > 1 condition
+ * in the above loop was so that the last multiply
+ * would get unrolled. We handle it here.
+ * It could underflow.
+ */
+ double t = dValue * tiny10pow[j];
+ if ( t == 0.0 ){
+ /*
+ * It did underflow.
+ * Look more closely at the result.
+ * If the exponent is just one too small,
+ * then use the minimum finite as our estimate
+ * value. Else call the result 0.0
+ * and punt it.
+ * ( I presume this could happen because
+ * rounding forces the result here to be
+ * an ULP or two less than
+ * Double.MIN_VALUE ).
+ */
+ t = dValue * 2.0;
+ t *= tiny10pow[j];
+ if ( t == 0.0 ){
+ return (isNegative)? -0.0 : 0.0;
+ }
+ t = Double.MIN_VALUE;
+ }
+ dValue = t;
+ }
+ }
+
+ /*
+ * dValue is now approximately the result.
+ * The hard part is adjusting it, by comparison
+ * with OldFDBigIntForTest arithmetic.
+ * Formulate the EXACT big-number result as
+ * bigD0 * 10^exp
+ */
+ OldFDBigIntForTest bigD0 = new OldFDBigIntForTest( lValue, digits, kDigits, nDigits );
+ exp = decExponent - nDigits;
+
+ correctionLoop:
+ while(true){
+ /* AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
+ * bigIntExp and bigIntNBits
+ */
+ OldFDBigIntForTest bigB = doubleToBigInt( dValue );
+
+ /*
+ * Scale bigD, bigB appropriately for
+ * big-integer operations.
+ * Naively, we multiply by powers of ten
+ * and powers of two. What we actually do
+ * is keep track of the powers of 5 and
+ * powers of 2 we would use, then factor out
+ * common divisors before doing the work.
+ */
+ int B2, B5; // powers of 2, 5 in bigB
+ int D2, D5; // powers of 2, 5 in bigD
+ int Ulp2; // powers of 2 in halfUlp.
+ if ( exp >= 0 ){
+ B2 = B5 = 0;
+ D2 = D5 = exp;
+ } else {
+ B2 = B5 = -exp;
+ D2 = D5 = 0;
+ }
+ if ( bigIntExp >= 0 ){
+ B2 += bigIntExp;
+ } else {
+ D2 -= bigIntExp;
+ }
+ Ulp2 = B2;
+ // shift bigB and bigD left by a number s. t.
+ // halfUlp is still an integer.
+ int hulpbias;
+ if ( bigIntExp+bigIntNBits <= -expBias+1 ){
+ // This is going to be a denormalized number
+ // (if not actually zero).
+ // half an ULP is at 2^-(expBias+expShift+1)
+ hulpbias = bigIntExp+ expBias + expShift;
+ } else {
+ hulpbias = expShift + 2 - bigIntNBits;
+ }
+ B2 += hulpbias;
+ D2 += hulpbias;
+ // if there are common factors of 2, we might just as well
+ // factor them out, as they add nothing useful.
+ int common2 = Math.min( B2, Math.min( D2, Ulp2 ) );
+ B2 -= common2;
+ D2 -= common2;
+ Ulp2 -= common2;
+ // do multiplications by powers of 5 and 2
+ bigB = multPow52( bigB, B5, B2 );
+ OldFDBigIntForTest bigD = multPow52( new OldFDBigIntForTest( bigD0 ), D5, D2 );
+ //
+ // to recap:
+ // bigB is the scaled-big-int version of our floating-point
+ // candidate.
+ // bigD is the scaled-big-int version of the exact value
+ // as we understand it.
+ // halfUlp is 1/2 an ulp of bigB, except for special cases
+ // of exact powers of 2
+ //
+ // the plan is to compare bigB with bigD, and if the difference
+ // is less than halfUlp, then we're satisfied. Otherwise,
+ // use the ratio of difference to halfUlp to calculate a fudge
+ // factor to add to the floating value, then go 'round again.
+ //
+ OldFDBigIntForTest diff;
+ int cmpResult;
+ boolean overvalue;
+ if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){
+ overvalue = true; // our candidate is too big.
+ diff = bigB.sub( bigD );
+ if ( (bigIntNBits == 1) && (bigIntExp > -expBias+1) ){
+ // candidate is a normalized exact power of 2 and
+ // is too big. We will be subtracting.
+ // For our purposes, ulp is the ulp of the
+ // next smaller range.
+ Ulp2 -= 1;
+ if ( Ulp2 < 0 ){
+ // rats. Cannot de-scale ulp this far.
+ // must scale diff in other direction.
+ Ulp2 = 0;
+ diff.lshiftMe( 1 );
+ }
+ }
+ } else if ( cmpResult < 0 ){
+ overvalue = false; // our candidate is too small.
+ diff = bigD.sub( bigB );
+ } else {
+ // the candidate is exactly right!
+ // this happens with surprising frequency
+ break correctionLoop;
+ }
+ OldFDBigIntForTest halfUlp = constructPow52( B5, Ulp2 );
+ if ( (cmpResult = diff.cmp( halfUlp ) ) < 0 ){
+ // difference is small.
+ // this is close enough
+ if (mustSetRoundDir) {
+ roundDir = overvalue ? -1 : 1;
+ }
+ break correctionLoop;
+ } else if ( cmpResult == 0 ){
+ // difference is exactly half an ULP
+ // round to some other value maybe, then finish
+ dValue += 0.5*ulp( dValue, overvalue );
+ // should check for bigIntNBits == 1 here??
+ if (mustSetRoundDir) {
+ roundDir = overvalue ? -1 : 1;
+ }
+ break correctionLoop;
+ } else {
+ // difference is non-trivial.
+ // could scale addend by ratio of difference to
+ // halfUlp here, if we bothered to compute that difference.
+ // Most of the time ( I hope ) it is about 1 anyway.
+ dValue += ulp( dValue, overvalue );
+ if ( dValue == 0.0 || dValue == Double.POSITIVE_INFINITY )
+ break correctionLoop; // oops. Fell off end of range.
+ continue; // try again.
+ }
+
+ }
+ return (isNegative)? -dValue : dValue;
+ }
+ }
+
+ /*
+ * Take a FloatingDecimal, which we presumably just scanned in,
+ * and find out what its value is, as a float.
+ * This is distinct from doubleValue() to avoid the extremely
+ * unlikely case of a double rounding error, wherein the conversion
+ * to double has one rounding error, and the conversion of that double
+ * to a float has another rounding error, IN THE WRONG DIRECTION,
+ * ( because of the preference to a zero low-order bit ).
+ */
+
+ public strictfp float floatValue(){
+ int kDigits = Math.min( nDigits, singleMaxDecimalDigits+1 );
+ int iValue;
+ float fValue;
+
+ // First, check for NaN and Infinity values
+ if(digits == infinity || digits == notANumber) {
+ if(digits == notANumber)
+ return Float.NaN;
+ else
+ return (isNegative?Float.NEGATIVE_INFINITY:Float.POSITIVE_INFINITY);
+ }
+ else {
+ /*
+ * convert the lead kDigits to an integer.
+ */
+ iValue = (int)digits[0]-(int)'0';
+ for ( int i=1; i < kDigits; i++ ){
+ iValue = iValue*10 + (int)digits[i]-(int)'0';
+ }
+ fValue = (float)iValue;
+ int exp = decExponent-kDigits;
+ /*
+ * iValue now contains an integer with the value of
+ * the first kDigits digits of the number.
+ * fValue contains the (float) of the same.
+ */
+
+ if ( nDigits <= singleMaxDecimalDigits ){
+ /*
+ * possibly an easy case.
+ * We know that the digits can be represented
+ * exactly. And if the exponent isn't too outrageous,
+ * the whole thing can be done with one operation,
+ * thus one rounding error.
+ * Note that all our constructors trim all leading and
+ * trailing zeros, so simple values (including zero)
+ * will always end up here.
+ */
+ if (exp == 0 || fValue == 0.0f)
+ return (isNegative)? -fValue : fValue; // small floating integer
+ else if ( exp >= 0 ){
+ if ( exp <= singleMaxSmallTen ){
+ /*
+ * Can get the answer with one operation,
+ * thus one roundoff.
+ */
+ fValue *= singleSmall10pow[exp];
+ return (isNegative)? -fValue : fValue;
+ }
+ int slop = singleMaxDecimalDigits - kDigits;
+ if ( exp <= singleMaxSmallTen+slop ){
+ /*
+ * We can multiply dValue by 10^(slop)
+ * and it is still "small" and exact.
+ * Then we can multiply by 10^(exp-slop)
+ * with one rounding.
+ */
+ fValue *= singleSmall10pow[slop];
+ fValue *= singleSmall10pow[exp-slop];
+ return (isNegative)? -fValue : fValue;
+ }
+ /*
+ * Else we have a hard case with a positive exp.
+ */
+ } else {
+ if ( exp >= -singleMaxSmallTen ){
+ /*
+ * Can get the answer in one division.
+ */
+ fValue /= singleSmall10pow[-exp];
+ return (isNegative)? -fValue : fValue;
+ }
+ /*
+ * Else we have a hard case with a negative exp.
+ */
+ }
+ } else if ( (decExponent >= nDigits) && (nDigits+decExponent <= maxDecimalDigits) ){
+ /*
+ * In double-precision, this is an exact floating integer.
+ * So we can compute to double, then shorten to float
+ * with one round, and get the right answer.
+ *
+ * First, finish accumulating digits.
+ * Then convert that integer to a double, multiply
+ * by the appropriate power of ten, and convert to float.
+ */
+ long lValue = (long)iValue;
+ for ( int i=kDigits; i < nDigits; i++ ){
+ lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
+ }
+ double dValue = (double)lValue;
+ exp = decExponent-nDigits;
+ dValue *= small10pow[exp];
+ fValue = (float)dValue;
+ return (isNegative)? -fValue : fValue;
+
+ }
+ /*
+ * Harder cases:
+ * The sum of digits plus exponent is greater than
+ * what we think we can do with one error.
+ *
+ * Start by weeding out obviously out-of-range
+ * results, then convert to double and go to
+ * common hard-case code.
+ */
+ if ( decExponent > singleMaxDecimalExponent+1 ){
+ /*
+ * Lets face it. This is going to be
+ * Infinity. Cut to the chase.
+ */
+ return (isNegative)? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+ } else if ( decExponent < singleMinDecimalExponent-1 ){
+ /*
+ * Lets face it. This is going to be
+ * zero. Cut to the chase.
+ */
+ return (isNegative)? -0.0f : 0.0f;
+ }
+
+ /*
+ * Here, we do 'way too much work, but throwing away
+ * our partial results, and going and doing the whole
+ * thing as double, then throwing away half the bits that computes
+ * when we convert back to float.
+ *
+ * The alternative is to reproduce the whole multiple-precision
+ * algorithm for float precision, or to try to parameterize it
+ * for common usage. The former will take about 400 lines of code,
+ * and the latter I tried without success. Thus the semi-hack
+ * answer here.
+ */
+ mustSetRoundDir = !fromHex;
+ double dValue = doubleValue();
+ return stickyRound( dValue );
+ }
+ }
+
+
+ /*
+ * All the positive powers of 10 that can be
+ * represented exactly in double/float.
+ */
+ private static final double small10pow[] = {
+ 1.0e0,
+ 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
+ 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
+ 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
+ 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
+ 1.0e21, 1.0e22
+ };
+
+ private static final float singleSmall10pow[] = {
+ 1.0e0f,
+ 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
+ 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
+ };
+
+ private static final double big10pow[] = {
+ 1e16, 1e32, 1e64, 1e128, 1e256 };
+ private static final double tiny10pow[] = {
+ 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
+
+ private static final int maxSmallTen = small10pow.length-1;
+ private static final int singleMaxSmallTen = singleSmall10pow.length-1;
+
+ private static final int small5pow[] = {
+ 1,
+ 5,
+ 5*5,
+ 5*5*5,
+ 5*5*5*5,
+ 5*5*5*5*5,
+ 5*5*5*5*5*5,
+ 5*5*5*5*5*5*5,
+ 5*5*5*5*5*5*5*5,
+ 5*5*5*5*5*5*5*5*5,
+ 5*5*5*5*5*5*5*5*5*5,
+ 5*5*5*5*5*5*5*5*5*5*5,
+ 5*5*5*5*5*5*5*5*5*5*5*5,
+ 5*5*5*5*5*5*5*5*5*5*5*5*5
+ };
+
+
+ private static final long long5pow[] = {
+ 1L,
+ 5L,
+ 5L*5,
+ 5L*5*5,
+ 5L*5*5*5,
+ 5L*5*5*5*5,
+ 5L*5*5*5*5*5,
+ 5L*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ };
+
+ // approximately ceil( log2( long5pow[i] ) )
+ private static final int n5bits[] = {
+ 0,
+ 3,
+ 5,
+ 7,
+ 10,
+ 12,
+ 14,
+ 17,
+ 19,
+ 21,
+ 24,
+ 26,
+ 28,
+ 31,
+ 33,
+ 35,
+ 38,
+ 40,
+ 42,
+ 45,
+ 47,
+ 49,
+ 52,
+ 54,
+ 56,
+ 59,
+ 61,
+ };
+
+ private static final char infinity[] = { 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y' };
+ private static final char notANumber[] = { 'N', 'a', 'N' };
+ private static final char zero[] = { '0', '0', '0', '0', '0', '0', '0', '0' };
+
+
+ /*
+ * Grammar is compatible with hexadecimal floating-point constants
+ * described in section 6.4.4.2 of the C99 specification.
+ */
+ private static Pattern hexFloatPattern = null;
+ private static synchronized Pattern getHexFloatPattern() {
+ if (hexFloatPattern == null) {
+ hexFloatPattern = Pattern.compile(
+ //1 234 56 7 8 9
+ "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
+ );
+ }
+ return hexFloatPattern;
+ }
+
+ /*
+ * Convert string s to a suitable floating decimal; uses the
+ * double constructor and set the roundDir variable appropriately
+ * in case the value is later converted to a float.
+ */
+ static OldFloatingDecimalForTest parseHexString(String s) {
+ // Verify string is a member of the hexadecimal floating-point
+ // string language.
+ Matcher m = getHexFloatPattern().matcher(s);
+ boolean validInput = m.matches();
+
+ if (!validInput) {
+ // Input does not match pattern
+ throw new NumberFormatException("For input string: \"" + s + "\"");
+ } else { // validInput
+ /*
+ * We must isolate the sign, significand, and exponent
+ * fields. The sign value is straightforward. Since
+ * floating-point numbers are stored with a normalized
+ * representation, the significand and exponent are
+ * interrelated.
+ *
+ * After extracting the sign, we normalized the
+ * significand as a hexadecimal value, calculating an
+ * exponent adjust for any shifts made during
+ * normalization. If the significand is zero, the
+ * exponent doesn't need to be examined since the output
+ * will be zero.
+ *
+ * Next the exponent in the input string is extracted.
+ * Afterwards, the significand is normalized as a *binary*
+ * value and the input value's normalized exponent can be
+ * computed. The significand bits are copied into a
+ * double significand; if the string has more logical bits
+ * than can fit in a double, the extra bits affect the
+ * round and sticky bits which are used to round the final
+ * value.
+ */
+
+ // Extract significand sign
+ String group1 = m.group(1);
+ double sign = (( group1 == null ) || group1.equals("+"))? 1.0 : -1.0;
+
+
+ // Extract Significand magnitude
+ /*
+ * Based on the form of the significand, calculate how the
+ * binary exponent needs to be adjusted to create a
+ * normalized *hexadecimal* floating-point number; that
+ * is, a number where there is one nonzero hex digit to
+ * the left of the (hexa)decimal point. Since we are
+ * adjusting a binary, not hexadecimal exponent, the
+ * exponent is adjusted by a multiple of 4.
+ *
+ * There are a number of significand scenarios to consider;
+ * letters are used in indicate nonzero digits:
+ *
+ * 1. 000xxxx => x.xxx normalized
+ * increase exponent by (number of x's - 1)*4
+ *
+ * 2. 000xxx.yyyy => x.xxyyyy normalized
+ * increase exponent by (number of x's - 1)*4
+ *
+ * 3. .000yyy => y.yy normalized
+ * decrease exponent by (number of zeros + 1)*4
+ *
+ * 4. 000.00000yyy => y.yy normalized
+ * decrease exponent by (number of zeros to right of point + 1)*4
+ *
+ * If the significand is exactly zero, return a properly
+ * signed zero.
+ */
+
+ String significandString =null;
+ int signifLength = 0;
+ int exponentAdjust = 0;
+ {
+ int leftDigits = 0; // number of meaningful digits to
+ // left of "decimal" point
+ // (leading zeros stripped)
+ int rightDigits = 0; // number of digits to right of
+ // "decimal" point; leading zeros
+ // must always be accounted for
+ /*
+ * The significand is made up of either
+ *
+ * 1. group 4 entirely (integer portion only)
+ *
+ * OR
+ *
+ * 2. the fractional portion from group 7 plus any
+ * (optional) integer portions from group 6.
+ */
+ String group4;
+ if( (group4 = m.group(4)) != null) { // Integer-only significand
+ // Leading zeros never matter on the integer portion
+ significandString = stripLeadingZeros(group4);
+ leftDigits = significandString.length();
+ }
+ else {
+ // Group 6 is the optional integer; leading zeros
+ // never matter on the integer portion
+ String group6 = stripLeadingZeros(m.group(6));
+ leftDigits = group6.length();
+
+ // fraction
+ String group7 = m.group(7);
+ rightDigits = group7.length();
+
+ // Turn "integer.fraction" into "integer"+"fraction"
+ significandString =
+ ((group6 == null)?"":group6) + // is the null
+ // check necessary?
+ group7;
+ }
+
+ significandString = stripLeadingZeros(significandString);
+ signifLength = significandString.length();
+
+ /*
+ * Adjust exponent as described above
+ */
+ if (leftDigits >= 1) { // Cases 1 and 2
+ exponentAdjust = 4*(leftDigits - 1);
+ } else { // Cases 3 and 4
+ exponentAdjust = -4*( rightDigits - signifLength + 1);
+ }
+
+ // If the significand is zero, the exponent doesn't
+ // matter; return a properly signed zero.
+
+ if (signifLength == 0) { // Only zeros in input
+ return new OldFloatingDecimalForTest(sign * 0.0);
+ }
+ }
+
+ // Extract Exponent
+ /*
+ * Use an int to read in the exponent value; this should
+ * provide more than sufficient range for non-contrived
+ * inputs. If reading the exponent in as an int does
+ * overflow, examine the sign of the exponent and
+ * significand to determine what to do.
+ */
+ String group8 = m.group(8);
+ boolean positiveExponent = ( group8 == null ) || group8.equals("+");
+ long unsignedRawExponent;
+ try {
+ unsignedRawExponent = Integer.parseInt(m.group(9));
+ }
+ catch (NumberFormatException e) {
+ // At this point, we know the exponent is
+ // syntactically well-formed as a sequence of
+ // digits. Therefore, if an NumberFormatException
+ // is thrown, it must be due to overflowing int's
+ // range. Also, at this point, we have already
+ // checked for a zero significand. Thus the signs
+ // of the exponent and significand determine the
+ // final result:
+ //
+ // significand
+ // + -
+ // exponent + +infinity -infinity
+ // - +0.0 -0.0
+ return new OldFloatingDecimalForTest(sign * (positiveExponent ?
+ Double.POSITIVE_INFINITY : 0.0));
+ }
+
+ long rawExponent =
+ (positiveExponent ? 1L : -1L) * // exponent sign
+ unsignedRawExponent; // exponent magnitude
+
+ // Calculate partially adjusted exponent
+ long exponent = rawExponent + exponentAdjust ;
+
+ // Starting copying non-zero bits into proper position in
+ // a long; copy explicit bit too; this will be masked
+ // later for normal values.
+
+ boolean round = false;
+ boolean sticky = false;
+ int bitsCopied=0;
+ int nextShift=0;
+ long significand=0L;
+ // First iteration is different, since we only copy
+ // from the leading significand bit; one more exponent
+ // adjust will be needed...
+
+ // IMPORTANT: make leadingDigit a long to avoid
+ // surprising shift semantics!
+ long leadingDigit = getHexDigit(significandString, 0);
+
+ /*
+ * Left shift the leading digit (53 - (bit position of
+ * leading 1 in digit)); this sets the top bit of the
+ * significand to 1. The nextShift value is adjusted
+ * to take into account the number of bit positions of
+ * the leadingDigit actually used. Finally, the
+ * exponent is adjusted to normalize the significand
+ * as a binary value, not just a hex value.
+ */
+ if (leadingDigit == 1) {
+ significand |= leadingDigit << 52;
+ nextShift = 52 - 4;
+ /* exponent += 0 */ }
+ else if (leadingDigit <= 3) { // [2, 3]
+ significand |= leadingDigit << 51;
+ nextShift = 52 - 5;
+ exponent += 1;
+ }
+ else if (leadingDigit <= 7) { // [4, 7]
+ significand |= leadingDigit << 50;
+ nextShift = 52 - 6;
+ exponent += 2;
+ }
+ else if (leadingDigit <= 15) { // [8, f]
+ significand |= leadingDigit << 49;
+ nextShift = 52 - 7;
+ exponent += 3;
+ } else {
+ throw new AssertionError("Result from digit conversion too large!");
+ }
+ // The preceding if-else could be replaced by a single
+ // code block based on the high-order bit set in
+ // leadingDigit. Given leadingOnePosition,
+
+ // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
+ // nextShift = 52 - (3 + leadingOnePosition);
+ // exponent += (leadingOnePosition-1);
+
+
+ /*
+ * Now the exponent variable is equal to the normalized
+ * binary exponent. Code below will make representation
+ * adjustments if the exponent is incremented after
+ * rounding (includes overflows to infinity) or if the
+ * result is subnormal.
+ */
+
+ // Copy digit into significand until the significand can't
+ // hold another full hex digit or there are no more input
+ // hex digits.
+ int i = 0;
+ for(i = 1;
+ i < signifLength && nextShift >= 0;
+ i++) {
+ long currentDigit = getHexDigit(significandString, i);
+ significand |= (currentDigit << nextShift);
+ nextShift-=4;
+ }
+
+ // After the above loop, the bulk of the string is copied.
+ // Now, we must copy any partial hex digits into the
+ // significand AND compute the round bit and start computing
+ // sticky bit.
+
+ if ( i < signifLength ) { // at least one hex input digit exists
+ long currentDigit = getHexDigit(significandString, i);
+
+ // from nextShift, figure out how many bits need
+ // to be copied, if any
+ switch(nextShift) { // must be negative
+ case -1:
+ // three bits need to be copied in; can
+ // set round bit
+ significand |= ((currentDigit & 0xEL) >> 1);
+ round = (currentDigit & 0x1L) != 0L;
+ break;
+
+ case -2:
+ // two bits need to be copied in; can
+ // set round and start sticky
+ significand |= ((currentDigit & 0xCL) >> 2);
+ round = (currentDigit &0x2L) != 0L;
+ sticky = (currentDigit & 0x1L) != 0;
+ break;
+
+ case -3:
+ // one bit needs to be copied in
+ significand |= ((currentDigit & 0x8L)>>3);
+ // Now set round and start sticky, if possible
+ round = (currentDigit &0x4L) != 0L;
+ sticky = (currentDigit & 0x3L) != 0;
+ break;
+
+ case -4:
+ // all bits copied into significand; set
+ // round and start sticky
+ round = ((currentDigit & 0x8L) != 0); // is top bit set?
+ // nonzeros in three low order bits?
+ sticky = (currentDigit & 0x7L) != 0;
+ break;
+
+ default:
+ throw new AssertionError("Unexpected shift distance remainder.");
+ // break;
+ }
+
+ // Round is set; sticky might be set.
+
+ // For the sticky bit, it suffices to check the
+ // current digit and test for any nonzero digits in
+ // the remaining unprocessed input.
+ i++;
+ while(i < signifLength && !sticky) {
+ currentDigit = getHexDigit(significandString,i);
+ sticky = sticky || (currentDigit != 0);
+ i++;
+ }
+
+ }
+ // else all of string was seen, round and sticky are
+ // correct as false.
+
+
+ // Check for overflow and update exponent accordingly.
+
+ if (exponent > Double.MAX_EXPONENT) { // Infinite result
+ // overflow to properly signed infinity
+ return new OldFloatingDecimalForTest(sign * Double.POSITIVE_INFINITY);
+ } else { // Finite return value
+ if (exponent <= Double.MAX_EXPONENT && // (Usually) normal result
+ exponent >= Double.MIN_EXPONENT) {
+
+ // The result returned in this block cannot be a
+ // zero or subnormal; however after the
+ // significand is adjusted from rounding, we could
+ // still overflow in infinity.
+
+ // AND exponent bits into significand; if the
+ // significand is incremented and overflows from
+ // rounding, this combination will update the
+ // exponent correctly, even in the case of
+ // Double.MAX_VALUE overflowing to infinity.
+
+ significand = (( (exponent +
+ (long)DoubleConsts.EXP_BIAS) <<
+ (DoubleConsts.SIGNIFICAND_WIDTH-1))
+ & DoubleConsts.EXP_BIT_MASK) |
+ (DoubleConsts.SIGNIF_BIT_MASK & significand);
+
+ } else { // Subnormal or zero
+ // (exponent < Double.MIN_EXPONENT)
+
+ if (exponent < (DoubleConsts.MIN_SUB_EXPONENT -1 )) {
+ // No way to round back to nonzero value
+ // regardless of significand if the exponent is
+ // less than -1075.
+ return new OldFloatingDecimalForTest(sign * 0.0);
+ } else { // -1075 <= exponent <= MIN_EXPONENT -1 = -1023
+ /*
+ * Find bit position to round to; recompute
+ * round and sticky bits, and shift
+ * significand right appropriately.
+ */
+
+ sticky = sticky || round;
+ round = false;
+
+ // Number of bits of significand to preserve is
+ // exponent - abs_min_exp +1
+ // check:
+ // -1075 +1074 + 1 = 0
+ // -1023 +1074 + 1 = 52
+
+ int bitsDiscarded = 53 -
+ ((int)exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
+ assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
+
+ // What to do here:
+ // First, isolate the new round bit
+ round = (significand & (1L << (bitsDiscarded -1))) != 0L;
+ if (bitsDiscarded > 1) {
+ // create mask to update sticky bits; low
+ // order bitsDiscarded bits should be 1
+ long mask = ~((~0L) << (bitsDiscarded -1));
+ sticky = sticky || ((significand & mask) != 0L ) ;
+ }
+
+ // Now, discard the bits
+ significand = significand >> bitsDiscarded;
+
+ significand = (( ((long)(Double.MIN_EXPONENT -1) + // subnorm exp.
+ (long)DoubleConsts.EXP_BIAS) <<
+ (DoubleConsts.SIGNIFICAND_WIDTH-1))
+ & DoubleConsts.EXP_BIT_MASK) |
+ (DoubleConsts.SIGNIF_BIT_MASK & significand);
+ }
+ }
+
+ // The significand variable now contains the currently
+ // appropriate exponent bits too.
+
+ /*
+ * Determine if significand should be incremented;
+ * making this determination depends on the least
+ * significant bit and the round and sticky bits.
+ *
+ * Round to nearest even rounding table, adapted from
+ * table 4.7 in "Computer Arithmetic" by IsraelKoren.
+ * The digit to the left of the "decimal" point is the
+ * least significant bit, the digits to the right of
+ * the point are the round and sticky bits
+ *
+ * Number Round(x)
+ * x0.00 x0.
+ * x0.01 x0.
+ * x0.10 x0.
+ * x0.11 x1. = x0. +1
+ * x1.00 x1.
+ * x1.01 x1.
+ * x1.10 x1. + 1
+ * x1.11 x1. + 1
+ */
+ boolean incremented = false;
+ boolean leastZero = ((significand & 1L) == 0L);
+ if( ( leastZero && round && sticky ) ||
+ ((!leastZero) && round )) {
+ incremented = true;
+ significand++;
+ }
+
+ OldFloatingDecimalForTest fd = new OldFloatingDecimalForTest(Math.copySign(
+ Double.longBitsToDouble(significand),
+ sign));
+
+ /*
+ * Set roundingDir variable field of fd properly so
+ * that the input string can be properly rounded to a
+ * float value. There are two cases to consider:
+ *
+ * 1. rounding to double discards sticky bit
+ * information that would change the result of a float
+ * rounding (near halfway case between two floats)
+ *
+ * 2. rounding to double rounds up when rounding up
+ * would not occur when rounding to float.
+ *
+ * For former case only needs to be considered when
+ * the bits rounded away when casting to float are all
+ * zero; otherwise, float round bit is properly set
+ * and sticky will already be true.
+ *
+ * The lower exponent bound for the code below is the
+ * minimum (normalized) subnormal exponent - 1 since a
+ * value with that exponent can round up to the
+ * minimum subnormal value and the sticky bit
+ * information must be preserved (i.e. case 1).
+ */
+ if ((exponent >= FloatConsts.MIN_SUB_EXPONENT-1) &&
+ (exponent <= Float.MAX_EXPONENT ) ){
+ // Outside above exponent range, the float value
+ // will be zero or infinity.
+
+ /*
+ * If the low-order 28 bits of a rounded double
+ * significand are 0, the double could be a
+ * half-way case for a rounding to float. If the
+ * double value is a half-way case, the double
+ * significand may have to be modified to round
+ * the the right float value (see the stickyRound
+ * method). If the rounding to double has lost
+ * what would be float sticky bit information, the
+ * double significand must be incremented. If the
+ * double value's significand was itself
+ * incremented, the float value may end up too
+ * large so the increment should be undone.
+ */
+ if ((significand & 0xfffffffL) == 0x0L) {
+ // For negative values, the sign of the
+ // roundDir is the same as for positive values
+ // since adding 1 increasing the significand's
+ // magnitude and subtracting 1 decreases the
+ // significand's magnitude. If neither round
+ // nor sticky is true, the double value is
+ // exact and no adjustment is required for a
+ // proper float rounding.
+ if( round || sticky) {
+ if (leastZero) { // prerounding lsb is 0
+ // If round and sticky were both true,
+ // and the least significant
+ // significand bit were 0, the rounded
+ // significand would not have its
+ // low-order bits be zero. Therefore,
+ // we only need to adjust the
+ // significand if round XOR sticky is
+ // true.
+ if (round ^ sticky) {
+ fd.roundDir = 1;
+ }
+ }
+ else { // prerounding lsb is 1
+ // If the prerounding lsb is 1 and the
+ // resulting significand has its
+ // low-order bits zero, the significand
+ // was incremented. Here, we undo the
+ // increment, which will ensure the
+ // right guard and sticky bits for the
+ // float rounding.
+ if (round)
+ fd.roundDir = -1;
+ }
+ }
+ }
+ }
+
+ fd.fromHex = true;
+ return fd;
+ }
+ }
+ }
+
+ /**
+ * Return <code>s</code> with any leading zeros removed.
+ */
+ static String stripLeadingZeros(String s) {
+ return s.replaceFirst("^0+", "");
+ }
+
+ /**
+ * Extract a hexadecimal digit from position <code>position</code>
+ * of string <code>s</code>.
+ */
+ static int getHexDigit(String s, int position) {
+ int value = Character.digit(s.charAt(position), 16);
+ if (value <= -1 || value >= 16) {
+ throw new AssertionError("Unexpected failure of digit conversion of " +
+ s.charAt(position));
+ }
+ return value;
+ }
+
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/internal/math/FloatingDecimal/TestFDBigInteger.java Tue Dec 22 12:17:25 2015 +0000
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.math.BigInteger;
+import java.util.Random;
+import jdk.internal.math.FDBigInteger;
+
+/**
+ * @test
+ * @bug 7032154
+ * @summary unit testys of FDBigInteger
+ * @modules java.base/jdk.internal.math
+ * @author Dmitry Nadezhin
+ */
+public class TestFDBigInteger {
+
+ private static final int MAX_P5 = 413;
+ private static final int MAX_P2 = 65;
+ private static final long LONG_SIGN_MASK = (1L << 63);
+ private static final BigInteger FIVE = BigInteger.valueOf(5);
+ private static final FDBigInteger MUTABLE_ZERO = FDBigInteger.valueOfPow52(0, 0).leftInplaceSub(FDBigInteger.valueOfPow52(0, 0));
+ private static final FDBigInteger IMMUTABLE_ZERO = FDBigInteger.valueOfPow52(0, 0).leftInplaceSub(FDBigInteger.valueOfPow52(0, 0));
+ private static final FDBigInteger IMMUTABLE_MILLION = genMillion1();
+ private static final FDBigInteger IMMUTABLE_BILLION = genBillion1();
+ private static final FDBigInteger IMMUTABLE_TEN18 = genTen18();
+
+ static {
+ IMMUTABLE_ZERO.makeImmutable();
+ IMMUTABLE_MILLION.makeImmutable();
+ IMMUTABLE_BILLION.makeImmutable();
+ IMMUTABLE_TEN18.makeImmutable();
+ }
+
+ private static FDBigInteger mutable(String hex, int offset) {
+ char[] chars = new BigInteger(hex, 16).toString().toCharArray();
+ return new FDBigInteger(0, chars, 0, chars.length).multByPow52(0, offset * 32);
+ }
+
+ private static FDBigInteger immutable(String hex, int offset) {
+ FDBigInteger fd = mutable(hex, offset);
+ fd.makeImmutable();
+ return fd;
+ }
+
+ private static BigInteger biPow52(int p5, int p2) {
+ return FIVE.pow(p5).shiftLeft(p2);
+ }
+
+ // data.length == 1, nWords == 1, offset == 0
+ private static FDBigInteger genMillion1() {
+ return FDBigInteger.valueOfPow52(6, 0).leftShift(6);
+ }
+
+ // data.length == 2, nWords == 1, offset == 0
+ private static FDBigInteger genMillion2() {
+ return FDBigInteger.valueOfMulPow52(1000000L, 0, 0);
+ }
+
+ // data.length == 1, nWords == 1, offset == 0
+ private static FDBigInteger genBillion1() {
+ return FDBigInteger.valueOfPow52(9, 0).leftShift(9);
+ }
+
+ // data.length == 2, nWords == 2, offset == 0
+ private static FDBigInteger genTen18() {
+ return FDBigInteger.valueOfPow52(18, 0).leftShift(18);
+ }
+
+ private static void check(BigInteger expected, FDBigInteger actual, String message) throws Exception {
+ if (!expected.equals(actual.toBigInteger())) {
+ throw new Exception(message + " result " + actual.toHexString() + " expected " + expected.toString(16));
+ }
+ }
+
+ private static void testValueOfPow52(int p5, int p2) throws Exception {
+ check(biPow52(p5, p2), FDBigInteger.valueOfPow52(p5, p2),
+ "valueOfPow52(" + p5 + "," + p2 + ")");
+ }
+
+ private static void testValueOfPow52() throws Exception {
+ for (int p5 = 0; p5 <= MAX_P5; p5++) {
+ for (int p2 = 0; p2 <= MAX_P2; p2++) {
+ testValueOfPow52(p5, p2);
+ }
+ }
+ }
+
+ private static void testValueOfMulPow52(long value, int p5, int p2) throws Exception {
+ BigInteger bi = BigInteger.valueOf(value & ~LONG_SIGN_MASK);
+ if (value < 0) {
+ bi = bi.setBit(63);
+ }
+ check(biPow52(p5, p2).multiply(bi), FDBigInteger.valueOfMulPow52(value, p5, p2),
+ "valueOfMulPow52(" + Long.toHexString(value) + "." + p5 + "," + p2 + ")");
+ }
+
+ private static void testValueOfMulPow52(long value, int p5) throws Exception {
+ testValueOfMulPow52(value, p5, 0);
+ testValueOfMulPow52(value, p5, 1);
+ testValueOfMulPow52(value, p5, 30);
+ testValueOfMulPow52(value, p5, 31);
+ testValueOfMulPow52(value, p5, 33);
+ testValueOfMulPow52(value, p5, 63);
+ }
+
+ private static void testValueOfMulPow52() throws Exception {
+ for (int p5 = 0; p5 <= MAX_P5; p5++) {
+ testValueOfMulPow52(0xFFFFFFFFL, p5);
+ testValueOfMulPow52(0x123456789AL, p5);
+ testValueOfMulPow52(0x7FFFFFFFFFFFFFFFL, p5);
+ testValueOfMulPow52(0xFFFFFFFFFFF54321L, p5);
+ }
+ }
+
+ private static void testLeftShift(FDBigInteger t, int shift, boolean isImmutable) throws Exception {
+ BigInteger bt = t.toBigInteger();
+ FDBigInteger r = t.leftShift(shift);
+ if ((bt.signum() == 0 || shift == 0 || !isImmutable) && r != t) {
+ throw new Exception("leftShift doesn't reuse its argument");
+ }
+ if (isImmutable) {
+ check(bt, t, "leftShift corrupts its argument");
+ }
+ check(bt.shiftLeft(shift), r, "leftShift returns wrong result");
+ }
+
+ private static void testLeftShift() throws Exception {
+ testLeftShift(IMMUTABLE_ZERO, 0, true);
+ testLeftShift(IMMUTABLE_ZERO, 10, true);
+ testLeftShift(MUTABLE_ZERO, 0, false);
+ testLeftShift(MUTABLE_ZERO, 10, false);
+
+ testLeftShift(IMMUTABLE_MILLION, 0, true);
+ testLeftShift(IMMUTABLE_MILLION, 1, true);
+ testLeftShift(IMMUTABLE_MILLION, 12, true);
+ testLeftShift(IMMUTABLE_MILLION, 13, true);
+ testLeftShift(IMMUTABLE_MILLION, 32, true);
+ testLeftShift(IMMUTABLE_MILLION, 33, true);
+ testLeftShift(IMMUTABLE_MILLION, 44, true);
+ testLeftShift(IMMUTABLE_MILLION, 45, true);
+
+ testLeftShift(genMillion1(), 0, false);
+ testLeftShift(genMillion1(), 1, false);
+ testLeftShift(genMillion1(), 12, false);
+ testLeftShift(genMillion1(), 13, false);
+ testLeftShift(genMillion1(), 25, false);
+ testLeftShift(genMillion1(), 26, false);
+ testLeftShift(genMillion1(), 32, false);
+ testLeftShift(genMillion1(), 33, false);
+ testLeftShift(genMillion1(), 44, false);
+ testLeftShift(genMillion1(), 45, false);
+
+ testLeftShift(genMillion2(), 0, false);
+ testLeftShift(genMillion2(), 1, false);
+ testLeftShift(genMillion2(), 12, false);
+ testLeftShift(genMillion2(), 13, false);
+ testLeftShift(genMillion2(), 25, false);
+ testLeftShift(genMillion2(), 26, false);
+ testLeftShift(genMillion2(), 32, false);
+ testLeftShift(genMillion2(), 33, false);
+ testLeftShift(genMillion2(), 44, false);
+ testLeftShift(genMillion2(), 45, false);
+ }
+
+ private static void testQuoRemIteration(FDBigInteger t, FDBigInteger s) throws Exception {
+ BigInteger bt = t.toBigInteger();
+ BigInteger bs = s.toBigInteger();
+ int q = t.quoRemIteration(s);
+ BigInteger[] qr = bt.divideAndRemainder(bs);
+ if (!BigInteger.valueOf(q).equals(qr[0])) {
+ throw new Exception("quoRemIteration returns incorrect quo");
+ }
+ check(qr[1].multiply(BigInteger.TEN), t, "quoRemIteration returns incorrect rem");
+ }
+
+ private static void testQuoRemIteration() throws Exception {
+ // IMMUTABLE_TEN18 == 0de0b6b3a7640000
+ // q = 0
+ testQuoRemIteration(mutable("00000001", 0), IMMUTABLE_TEN18);
+ testQuoRemIteration(mutable("00000001", 1), IMMUTABLE_TEN18);
+ testQuoRemIteration(mutable("0de0b6b2", 1), IMMUTABLE_TEN18);
+ // q = 1 -> q = 0
+ testQuoRemIteration(mutable("0de0b6b3", 1), IMMUTABLE_TEN18);
+ testQuoRemIteration(mutable("0de0b6b3a763FFFF", 0), IMMUTABLE_TEN18);
+ // q = 1
+ testQuoRemIteration(mutable("0de0b6b3a7640000", 0), IMMUTABLE_TEN18);
+ testQuoRemIteration(mutable("0de0b6b3FFFFFFFF", 0), IMMUTABLE_TEN18);
+ testQuoRemIteration(mutable("8ac72304", 1), IMMUTABLE_TEN18);
+ testQuoRemIteration(mutable("0de0b6b400000000", 0), IMMUTABLE_TEN18);
+ testQuoRemIteration(mutable("8ac72305", 1), IMMUTABLE_TEN18);
+ // q = 18
+ testQuoRemIteration(mutable("FFFFFFFF", 1), IMMUTABLE_TEN18);
+ }
+
+ private static void testCmp(FDBigInteger t, FDBigInteger o) throws Exception {
+ BigInteger bt = t.toBigInteger();
+ BigInteger bo = o.toBigInteger();
+ int cmp = t.cmp(o);
+ int bcmp = bt.compareTo(bo);
+ if (bcmp != cmp) {
+ throw new Exception("cmp returns " + cmp + " expected " + bcmp);
+ }
+ check(bt, t, "cmp corrupts this");
+ check(bo, o, "cmp corrupts other");
+ if (o.cmp(t) != -cmp) {
+ throw new Exception("asymmetrical cmp");
+ }
+ check(bt, t, "cmp corrupts this");
+ check(bo, o, "cmp corrupts other");
+ }
+
+ private static void testCmp() throws Exception {
+ testCmp(mutable("FFFFFFFF", 0), mutable("100000000", 0));
+ testCmp(mutable("FFFFFFFF", 0), mutable("1", 1));
+ testCmp(mutable("5", 0), mutable("6", 0));
+ testCmp(mutable("5", 0), mutable("5", 0));
+ testCmp(mutable("5000000001", 0), mutable("500000001", 0));
+ testCmp(mutable("5000000001", 0), mutable("6", 1));
+ testCmp(mutable("5000000001", 0), mutable("5", 1));
+ testCmp(mutable("5000000000", 0), mutable("5", 1));
+ }
+
+ private static void testCmpPow52(FDBigInteger t, int p5, int p2) throws Exception {
+ FDBigInteger o = FDBigInteger.valueOfPow52(p5, p2);
+ BigInteger bt = t.toBigInteger();
+ BigInteger bo = biPow52(p5, p2);
+ int cmp = t.cmp(o);
+ int bcmp = bt.compareTo(bo);
+ if (bcmp != cmp) {
+ throw new Exception("cmpPow52 returns " + cmp + " expected " + bcmp);
+ }
+ check(bt, t, "cmpPow52 corrupts this");
+ check(bo, o, "cmpPow5 corrupts other");
+ }
+
+ private static void testCmpPow52() throws Exception {
+ testCmpPow52(mutable("00000002", 1), 0, 31);
+ testCmpPow52(mutable("00000002", 1), 0, 32);
+ testCmpPow52(mutable("00000002", 1), 0, 33);
+ testCmpPow52(mutable("00000002", 1), 0, 34);
+ testCmpPow52(mutable("00000002", 1), 0, 64);
+ testCmpPow52(mutable("00000003", 1), 0, 32);
+ testCmpPow52(mutable("00000003", 1), 0, 33);
+ testCmpPow52(mutable("00000003", 1), 0, 34);
+ }
+
+ private static void testAddAndCmp(FDBigInteger t, FDBigInteger x, FDBigInteger y) throws Exception {
+ BigInteger bt = t.toBigInteger();
+ BigInteger bx = x.toBigInteger();
+ BigInteger by = y.toBigInteger();
+ int cmp = t.addAndCmp(x, y);
+ int bcmp = bt.compareTo(bx.add(by));
+ if (bcmp != cmp) {
+ throw new Exception("addAndCmp returns " + cmp + " expected " + bcmp);
+ }
+ check(bt, t, "addAndCmp corrupts this");
+ check(bx, x, "addAndCmp corrupts x");
+ check(by, y, "addAndCmp corrupts y");
+ }
+
+ private static void testAddAndCmp() throws Exception {
+ testAddAndCmp(MUTABLE_ZERO, MUTABLE_ZERO, MUTABLE_ZERO);
+ testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, MUTABLE_ZERO);
+ testAddAndCmp(mutable("00000001", 0), mutable("00000001", 0), MUTABLE_ZERO);
+ testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, mutable("00000001", 0));
+ testAddAndCmp(mutable("00000001", 0), mutable("00000002", 0), MUTABLE_ZERO);
+ testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, mutable("00000002", 0));
+ testAddAndCmp(mutable("00000001", 2), mutable("FFFFFFFF", 0), mutable("FFFFFFFF", 0));
+ testAddAndCmp(mutable("00000001", 0), mutable("00000001", 1), mutable("00000001", 0));
+
+ testAddAndCmp(mutable("00000001", 2), mutable("0F0F0F0F80000000", 1), mutable("F0F0F0F080000000", 1));
+ testAddAndCmp(mutable("00000001", 2), mutable("0F0F0F0E80000000", 1), mutable("F0F0F0F080000000", 1));
+
+ testAddAndCmp(mutable("00000002", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
+ testAddAndCmp(mutable("00000003", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
+ testAddAndCmp(mutable("00000004", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
+ testAddAndCmp(mutable("00000005", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
+
+ testAddAndCmp(mutable("00000001", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
+ testAddAndCmp(mutable("00000001", 2), mutable("8000000000000000", 0), mutable("8000000000000001", 0));
+ testAddAndCmp(mutable("00000002", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
+ testAddAndCmp(mutable("00000003", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
+ }
+
+ private static void testMultBy10(FDBigInteger t, boolean isImmutable) throws Exception {
+ BigInteger bt = t.toBigInteger();
+ FDBigInteger r = t.multBy10();
+ if ((bt.signum() == 0 || !isImmutable) && r != t) {
+ throw new Exception("multBy10 of doesn't reuse its argument");
+ }
+ if (isImmutable) {
+ check(bt, t, "multBy10 corrupts its argument");
+ }
+ check(bt.multiply(BigInteger.TEN), r, "multBy10 returns wrong result");
+ }
+
+ private static void testMultBy10() throws Exception {
+ for (int p5 = 0; p5 <= MAX_P5; p5++) {
+ for (int p2 = 0; p2 <= MAX_P2; p2++) {
+ // This strange way of creating a value ensures that it is mutable.
+ FDBigInteger value = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
+ testMultBy10(value, false);
+ value.makeImmutable();
+ testMultBy10(value, true);
+ }
+ }
+ }
+
+ private static void testMultByPow52(FDBigInteger t, int p5, int p2) throws Exception {
+ BigInteger bt = t.toBigInteger();
+ FDBigInteger r = t.multByPow52(p5, p2);
+ if (bt.signum() == 0 && r != t) {
+ throw new Exception("multByPow52 of doesn't reuse its argument");
+ }
+ check(bt.multiply(biPow52(p5, p2)), r, "multByPow52 returns wrong result");
+ }
+
+ private static void testMultByPow52() throws Exception {
+ for (int p5 = 0; p5 <= MAX_P5; p5++) {
+ for (int p2 = 0; p2 <= MAX_P2; p2++) {
+ // This strange way of creating a value ensures that it is mutable.
+ FDBigInteger value = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
+ testMultByPow52(value, p5, p2);
+ }
+ }
+ }
+
+ private static void testLeftInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable) throws Exception {
+ BigInteger biLeft = left.toBigInteger();
+ BigInteger biRight = right.toBigInteger();
+ FDBigInteger diff = left.leftInplaceSub(right);
+ if (!isImmutable && diff != left) {
+ throw new Exception("leftInplaceSub of doesn't reuse its argument");
+ }
+ if (isImmutable) {
+ check(biLeft, left, "leftInplaceSub corrupts its left immutable argument");
+ }
+ check(biRight, right, "leftInplaceSub corrupts its right argument");
+ check(biLeft.subtract(biRight), diff, "leftInplaceSub returns wrong result");
+ }
+
+ private static void testLeftInplaceSub() throws Exception {
+ for (int p5 = 0; p5 <= MAX_P5; p5++) {
+ for (int p2 = 0; p2 <= MAX_P2; p2++) {
+// for (int p5r = 0; p5r <= p5; p5r += 10) {
+// for (int p2r = 0; p2r <= p2; p2r += 10) {
+ for (int p5r = 0; p5r <= p5; p5r++) {
+ for (int p2r = 0; p2r <= p2; p2r++) {
+ // This strange way of creating a value ensures that it is mutable.
+ FDBigInteger left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
+ FDBigInteger right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
+ testLeftInplaceSub(left, right, false);
+ left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
+ left.makeImmutable();
+ testLeftInplaceSub(left, right, true);
+ }
+ }
+ }
+ }
+ }
+
+ private static void testRightInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable) throws Exception {
+ BigInteger biLeft = left.toBigInteger();
+ BigInteger biRight = right.toBigInteger();
+ FDBigInteger diff = left.rightInplaceSub(right);
+ if (!isImmutable && diff != right) {
+ throw new Exception("rightInplaceSub of doesn't reuse its argument");
+ }
+ check(biLeft, left, "leftInplaceSub corrupts its left argument");
+ if (isImmutable) {
+ check(biRight, right, "leftInplaceSub corrupts its right immutable argument");
+ }
+ try {
+ check(biLeft.subtract(biRight), diff, "rightInplaceSub returns wrong result");
+ } catch (Exception e) {
+ System.out.println(biLeft+" - "+biRight+" = "+biLeft.subtract(biRight));
+ throw e;
+ }
+ }
+
+ private static void testRightInplaceSub() throws Exception {
+ for (int p5 = 0; p5 <= MAX_P5; p5++) {
+ for (int p2 = 0; p2 <= MAX_P2; p2++) {
+// for (int p5r = 0; p5r <= p5; p5r += 10) {
+// for (int p2r = 0; p2r <= p2; p2r += 10) {
+ for (int p5r = 0; p5r <= p5; p5r++) {
+ for (int p2r = 0; p2r <= p2; p2r++) {
+ // This strange way of creating a value ensures that it is mutable.
+ FDBigInteger left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
+ FDBigInteger right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
+ testRightInplaceSub(left, right, false);
+ right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
+ right.makeImmutable();
+ testRightInplaceSub(left, right, true);
+ }
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ testValueOfPow52();
+ testValueOfMulPow52();
+ testLeftShift();
+ testQuoRemIteration();
+ testCmp();
+ testCmpPow52();
+ testAddAndCmp();
+ // Uncomment the following for more comprehensize but slow testing.
+ // testLeftInplaceSub();
+ // testMultBy10();
+ // testMultByPow52();
+ // testRightInplaceSub();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/internal/math/FloatingDecimal/TestFloatingDecimal.java Tue Dec 22 12:17:25 2015 +0000
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.Random;
+import jdk.internal.math.FloatingDecimal;
+
+/*
+OldFloatingDecimalForTest
+
+public class OldFloatingDecimalForTest {
+ public boolean digitsRoundedUp();
+ public OldFloatingDecimalForTest(double);
+ public OldFloatingDecimalForTest(float);
+ public boolean decimalDigitsExact();
+ public java.lang.String toString();
+ public java.lang.String toJavaFormatString();
+ public void appendTo(java.lang.Appendable);
+ public static OldFloatingDecimalForTest readJavaFormatString(java.lang.String) throws java.lang.NumberFormatException;
+ public strictfp double doubleValue();
+ public strictfp float floatValue();
+}
+
+jdk.internal.math.FloatingDecimal
+
+public class jdk.internal.math.FloatingDecimal {
+ public jdk.internal.math.FloatingDecimal();
+ public static java.lang.String toJavaFormatString(double);
+ public static java.lang.String toJavaFormatString(float);
+ public static void appendTo(double, java.lang.Appendable);
+ public static void appendTo(float, java.lang.Appendable);
+ public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException;
+ public static float parseFloat(java.lang.String) throws java.lang.NumberFormatException;
+ public static jdk.internal.math.FloatingDecimal$AbstractD2ABuffer getD2ABuffer(double);
+}
+*/
+
+/**
+ * @test
+ * @bug 7032154
+ * @summary unit tests of FloatingDecimal
+ * @modules java.base/jdk.internal.math
+ * @library /java/lang/Math
+ * @build DoubleConsts FloatConsts
+ * @run main TestFloatingDecimal
+ * @author Brian Burkhalter
+ * @key randomness
+ */
+public class TestFloatingDecimal {
+ private static enum ResultType {
+ RESULT_EXCEPTION,
+ RESULT_PRINT
+ }
+
+ private static final ResultType RESULT_TYPE = ResultType.RESULT_PRINT;
+ private static final int NUM_RANDOM_TESTS = 100000;
+
+ private static final Random RANDOM = new Random();
+
+ private static void result(String message) {
+ switch (RESULT_TYPE) {
+ case RESULT_EXCEPTION:
+ throw new RuntimeException(message);
+ case RESULT_PRINT:
+ System.err.println(message);
+ break;
+ default:
+ assert false;
+ }
+ }
+
+ private static int check(String test, Object expected, Object actual) {
+ int failures = 0;
+ if(!actual.equals(expected)) {
+ failures++;
+ result("Test "+test+" expected "+expected+" but obtained "+actual);
+ }
+ return failures;
+ }
+
+ private static int testAppendToDouble() {
+ System.out.println(" testAppendToDouble");
+ int failures = 0;
+
+ for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
+ double[] d = new double[] {
+ RANDOM.nextLong(),
+ RANDOM.nextGaussian(),
+ RANDOM.nextDouble()*Double.MAX_VALUE
+ };
+ for(int j = 0; j < d.length; j++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]);
+ StringBuilder sb = new StringBuilder();
+ ofd.appendTo(sb);
+ String oldString = sb.toString();
+ sb = new StringBuilder();
+ FloatingDecimal.appendTo(d[j], sb);
+ String newString = sb.toString();
+ failures += check("testAppendToDouble", oldString, newString);
+ }
+ }
+
+ return failures;
+ }
+
+ private static int testAppendToFloat() {
+ System.out.println(" testAppendToFloat");
+ int failures = 0;
+
+ for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
+ float[] f = new float[] {
+ RANDOM.nextLong(),
+ (float)RANDOM.nextGaussian(),
+ RANDOM.nextFloat()*Float.MAX_VALUE
+ };
+ for(int j = 0; j < f.length; j++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]);
+ StringBuilder sb = new StringBuilder();
+ ofd.appendTo(sb);
+ String oldString = sb.toString();
+ sb = new StringBuilder();
+ FloatingDecimal.appendTo(f[j], sb);
+ String newString = sb.toString();
+ failures += check("testAppendToFloat", oldString, newString);
+ }
+ }
+
+ return failures;
+ }
+
+ private static int testAppendTo() {
+ System.out.println("testAppendTo");
+ int failures = 0;
+
+ failures += testAppendToDouble();
+ failures += testAppendToFloat();
+
+ return failures;
+ }
+
+ private static int testParseDouble() {
+ System.out.println(" testParseDouble");
+ int failures = 0;
+
+ for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
+ double[] d = new double[] {
+ RANDOM.nextLong(),
+ RANDOM.nextGaussian(),
+ RANDOM.nextDouble()*Double.MAX_VALUE
+ };
+ for(int j = 0; j < d.length; j++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]);
+ String javaFormatString = ofd.toJavaFormatString();
+ ofd = OldFloatingDecimalForTest.readJavaFormatString(javaFormatString);
+ double oldDouble = ofd.doubleValue();
+ double newDouble = FloatingDecimal.parseDouble(javaFormatString);
+ failures += check("testParseDouble", oldDouble, newDouble);
+ }
+ }
+
+ return failures;
+ }
+
+ private static int testParseFloat() {
+ System.out.println(" testParseFloat");
+ int failures = 0;
+
+ for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
+ float[] f = new float[] {
+ RANDOM.nextInt(),
+ (float)RANDOM.nextGaussian(),
+ RANDOM.nextFloat()*Float.MAX_VALUE
+ };
+ for(int j = 0; j < f.length; j++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]);
+ String javaFormatString = ofd.toJavaFormatString();
+ ofd = OldFloatingDecimalForTest.readJavaFormatString(javaFormatString);
+ float oldFloat = ofd.floatValue();
+ float newFloat = FloatingDecimal.parseFloat(javaFormatString);
+ failures += check("testParseFloat", oldFloat, newFloat);
+ }
+ }
+
+ return failures;
+ }
+
+ private static int testParse() {
+ System.out.println("testParse");
+ int failures = 0;
+
+ failures += testParseDouble();
+ failures += testParseFloat();
+
+ return failures;
+ }
+
+ private static int testToJavaFormatStringDoubleFixed() {
+ System.out.println(" testToJavaFormatStringDoubleFixed");
+ int failures = 0;
+
+ double[] d = new double [] {
+ -5.9522650387500933e18, // dtoa() fast path
+ 0.872989018674569, // dtoa() fast iterative - long
+ 1.1317400099603851e308 // dtoa() slow iterative
+ };
+
+ for(int i = 0; i < d.length; i++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[i]);
+ failures += check("testToJavaFormatStringDoubleFixed", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(d[i]));
+ }
+
+ return failures;
+ }
+
+ private static int testToJavaFormatStringDoubleRandom() {
+ System.out.println(" testToJavaFormatStringDoubleRandom");
+ int failures = 0;
+
+ for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
+ double[] d = new double[] {
+ RANDOM.nextLong(),
+ RANDOM.nextGaussian(),
+ RANDOM.nextDouble()*Double.MAX_VALUE
+ };
+ for(int j = 0; j < d.length; j++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]);
+ failures += check("testToJavaFormatStringDoubleRandom", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(d[j]));
+ }
+ }
+
+ return failures;
+ }
+
+ private static int testToJavaFormatStringDouble() {
+ System.out.println(" testToJavaFormatStringDouble");
+ int failures = 0;
+ failures += testToJavaFormatStringDoubleFixed();
+ failures += testToJavaFormatStringDoubleRandom();
+ return failures;
+ }
+
+ private static int testToJavaFormatStringFloatFixed() {
+ System.out.println(" testToJavaFormatStringFloatFixed");
+ int failures = 0;
+
+ float[] f = new float[] {
+ -9.8784166e8f, // dtoa() fast path
+ 0.70443946f, // dtoa() fast iterative - int
+ 1.8254228e37f // dtoa() slow iterative
+ };
+
+ for(int i = 0; i < f.length; i++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[i]);
+ failures += check("testToJavaFormatStringFloatFixed", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(f[i]));
+ }
+
+ return failures;
+ }
+
+ private static int testToJavaFormatStringFloatRandom() {
+ System.out.println(" testToJavaFormatStringFloatRandom");
+ int failures = 0;
+
+ for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
+ float[] f = new float[] {
+ RANDOM.nextInt(),
+ (float)RANDOM.nextGaussian(),
+ RANDOM.nextFloat()*Float.MAX_VALUE
+ };
+ for(int j = 0; j < f.length; j++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]);
+ failures += check("testToJavaFormatStringFloatRandom", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(f[j]));
+ }
+ }
+
+ return failures;
+ }
+
+ private static int testToJavaFormatStringFloat() {
+ System.out.println(" testToJavaFormatStringFloat");
+ int failures = 0;
+
+ failures += testToJavaFormatStringFloatFixed();
+ failures += testToJavaFormatStringFloatRandom();
+
+ return failures;
+ }
+
+ private static int testToJavaFormatString() {
+ System.out.println("testToJavaFormatString");
+ int failures = 0;
+
+ failures += testToJavaFormatStringDouble();
+ failures += testToJavaFormatStringFloat();
+
+ return failures;
+ }
+
+ public static void main(String[] args) {
+ int failures = 0;
+
+ failures += testAppendTo();
+ failures += testParse();
+ failures += testToJavaFormatString();
+
+ if (failures != 0) {
+ throw new RuntimeException("" + failures + " failures while testing FloatingDecimal");
+ }
+ }
+}
--- a/jdk/test/sun/misc/FloatingDecimal/OldFDBigIntForTest.java Tue Dec 22 11:07:17 2015 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,491 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-//package sun.misc;
-
-/*
- * A really, really simple bigint package
- * tailored to the needs of floating base conversion.
- */
-class OldFDBigIntForTest {
- int nWords; // number of words used
- int data[]; // value: data[0] is least significant
-
-
- public OldFDBigIntForTest( int v ){
- nWords = 1;
- data = new int[1];
- data[0] = v;
- }
-
- public OldFDBigIntForTest( long v ){
- data = new int[2];
- data[0] = (int)v;
- data[1] = (int)(v>>>32);
- nWords = (data[1]==0) ? 1 : 2;
- }
-
- public OldFDBigIntForTest( OldFDBigIntForTest other ){
- data = new int[nWords = other.nWords];
- System.arraycopy( other.data, 0, data, 0, nWords );
- }
-
- private OldFDBigIntForTest( int [] d, int n ){
- data = d;
- nWords = n;
- }
-
- public OldFDBigIntForTest( long seed, char digit[], int nd0, int nd ){
- int n= (nd+8)/9; // estimate size needed.
- if ( n < 2 ) n = 2;
- data = new int[n]; // allocate enough space
- data[0] = (int)seed; // starting value
- data[1] = (int)(seed>>>32);
- nWords = (data[1]==0) ? 1 : 2;
- int i = nd0;
- int limit = nd-5; // slurp digits 5 at a time.
- int v;
- while ( i < limit ){
- int ilim = i+5;
- v = (int)digit[i++]-(int)'0';
- while( i <ilim ){
- v = 10*v + (int)digit[i++]-(int)'0';
- }
- multaddMe( 100000, v); // ... where 100000 is 10^5.
- }
- int factor = 1;
- v = 0;
- while ( i < nd ){
- v = 10*v + (int)digit[i++]-(int)'0';
- factor *= 10;
- }
- if ( factor != 1 ){
- multaddMe( factor, v );
- }
- }
-
- /*
- * Left shift by c bits.
- * Shifts this in place.
- */
- public void
- lshiftMe( int c )throws IllegalArgumentException {
- if ( c <= 0 ){
- if ( c == 0 )
- return; // silly.
- else
- throw new IllegalArgumentException("negative shift count");
- }
- int wordcount = c>>5;
- int bitcount = c & 0x1f;
- int anticount = 32-bitcount;
- int t[] = data;
- int s[] = data;
- if ( nWords+wordcount+1 > t.length ){
- // reallocate.
- t = new int[ nWords+wordcount+1 ];
- }
- int target = nWords+wordcount;
- int src = nWords-1;
- if ( bitcount == 0 ){
- // special hack, since an anticount of 32 won't go!
- System.arraycopy( s, 0, t, wordcount, nWords );
- target = wordcount-1;
- } else {
- t[target--] = s[src]>>>anticount;
- while ( src >= 1 ){
- t[target--] = (s[src]<<bitcount) | (s[--src]>>>anticount);
- }
- t[target--] = s[src]<<bitcount;
- }
- while( target >= 0 ){
- t[target--] = 0;
- }
- data = t;
- nWords += wordcount + 1;
- // may have constructed high-order word of 0.
- // if so, trim it
- while ( nWords > 1 && data[nWords-1] == 0 )
- nWords--;
- }
-
- /*
- * normalize this number by shifting until
- * the MSB of the number is at 0x08000000.
- * This is in preparation for quoRemIteration, below.
- * The idea is that, to make division easier, we want the
- * divisor to be "normalized" -- usually this means shifting
- * the MSB into the high words sign bit. But because we know that
- * the quotient will be 0 < q < 10, we would like to arrange that
- * the dividend not span up into another word of precision.
- * (This needs to be explained more clearly!)
- */
- public int
- normalizeMe() throws IllegalArgumentException {
- int src;
- int wordcount = 0;
- int bitcount = 0;
- int v = 0;
- for ( src= nWords-1 ; src >= 0 && (v=data[src]) == 0 ; src--){
- wordcount += 1;
- }
- if ( src < 0 ){
- // oops. Value is zero. Cannot normalize it!
- throw new IllegalArgumentException("zero value");
- }
- /*
- * In most cases, we assume that wordcount is zero. This only
- * makes sense, as we try not to maintain any high-order
- * words full of zeros. In fact, if there are zeros, we will
- * simply SHORTEN our number at this point. Watch closely...
- */
- nWords -= wordcount;
- /*
- * Compute how far left we have to shift v s.t. its highest-
- * order bit is in the right place. Then call lshiftMe to
- * do the work.
- */
- if ( (v & 0xf0000000) != 0 ){
- // will have to shift up into the next word.
- // too bad.
- for( bitcount = 32 ; (v & 0xf0000000) != 0 ; bitcount-- )
- v >>>= 1;
- } else {
- while ( v <= 0x000fffff ){
- // hack: byte-at-a-time shifting
- v <<= 8;
- bitcount += 8;
- }
- while ( v <= 0x07ffffff ){
- v <<= 1;
- bitcount += 1;
- }
- }
- if ( bitcount != 0 )
- lshiftMe( bitcount );
- return bitcount;
- }
-
- /*
- * Multiply a OldFDBigIntForTest by an int.
- * Result is a new OldFDBigIntForTest.
- */
- public OldFDBigIntForTest
- mult( int iv ) {
- long v = iv;
- int r[];
- long p;
-
- // guess adequate size of r.
- r = new int[ ( v * ((long)data[nWords-1]&0xffffffffL) > 0xfffffffL ) ? nWords+1 : nWords ];
- p = 0L;
- for( int i=0; i < nWords; i++ ) {
- p += v * ((long)data[i]&0xffffffffL);
- r[i] = (int)p;
- p >>>= 32;
- }
- if ( p == 0L){
- return new OldFDBigIntForTest( r, nWords );
- } else {
- r[nWords] = (int)p;
- return new OldFDBigIntForTest( r, nWords+1 );
- }
- }
-
- /*
- * Multiply a OldFDBigIntForTest by an int and add another int.
- * Result is computed in place.
- * Hope it fits!
- */
- public void
- multaddMe( int iv, int addend ) {
- long v = iv;
- long p;
-
- // unroll 0th iteration, doing addition.
- p = v * ((long)data[0]&0xffffffffL) + ((long)addend&0xffffffffL);
- data[0] = (int)p;
- p >>>= 32;
- for( int i=1; i < nWords; i++ ) {
- p += v * ((long)data[i]&0xffffffffL);
- data[i] = (int)p;
- p >>>= 32;
- }
- if ( p != 0L){
- data[nWords] = (int)p; // will fail noisily if illegal!
- nWords++;
- }
- }
-
- /*
- * Multiply a OldFDBigIntForTest by another OldFDBigIntForTest.
- * Result is a new OldFDBigIntForTest.
- */
- public OldFDBigIntForTest
- mult( OldFDBigIntForTest other ){
- // crudely guess adequate size for r
- int r[] = new int[ nWords + other.nWords ];
- int i;
- // I think I am promised zeros...
-
- for( i = 0; i < this.nWords; i++ ){
- long v = (long)this.data[i] & 0xffffffffL; // UNSIGNED CONVERSION
- long p = 0L;
- int j;
- for( j = 0; j < other.nWords; j++ ){
- p += ((long)r[i+j]&0xffffffffL) + v*((long)other.data[j]&0xffffffffL); // UNSIGNED CONVERSIONS ALL 'ROUND.
- r[i+j] = (int)p;
- p >>>= 32;
- }
- r[i+j] = (int)p;
- }
- // compute how much of r we actually needed for all that.
- for ( i = r.length-1; i> 0; i--)
- if ( r[i] != 0 )
- break;
- return new OldFDBigIntForTest( r, i+1 );
- }
-
- /*
- * Add one OldFDBigIntForTest to another. Return a OldFDBigIntForTest
- */
- public OldFDBigIntForTest
- add( OldFDBigIntForTest other ){
- int i;
- int a[], b[];
- int n, m;
- long c = 0L;
- // arrange such that a.nWords >= b.nWords;
- // n = a.nWords, m = b.nWords
- if ( this.nWords >= other.nWords ){
- a = this.data;
- n = this.nWords;
- b = other.data;
- m = other.nWords;
- } else {
- a = other.data;
- n = other.nWords;
- b = this.data;
- m = this.nWords;
- }
- int r[] = new int[ n ];
- for ( i = 0; i < n; i++ ){
- c += (long)a[i] & 0xffffffffL;
- if ( i < m ){
- c += (long)b[i] & 0xffffffffL;
- }
- r[i] = (int) c;
- c >>= 32; // signed shift.
- }
- if ( c != 0L ){
- // oops -- carry out -- need longer result.
- int s[] = new int[ r.length+1 ];
- System.arraycopy( r, 0, s, 0, r.length );
- s[i++] = (int)c;
- return new OldFDBigIntForTest( s, i );
- }
- return new OldFDBigIntForTest( r, i );
- }
-
- /*
- * Subtract one OldFDBigIntForTest from another. Return a OldFDBigIntForTest
- * Assert that the result is positive.
- */
- public OldFDBigIntForTest
- sub( OldFDBigIntForTest other ){
- int r[] = new int[ this.nWords ];
- int i;
- int n = this.nWords;
- int m = other.nWords;
- int nzeros = 0;
- long c = 0L;
- for ( i = 0; i < n; i++ ){
- c += (long)this.data[i] & 0xffffffffL;
- if ( i < m ){
- c -= (long)other.data[i] & 0xffffffffL;
- }
- if ( ( r[i] = (int) c ) == 0 )
- nzeros++;
- else
- nzeros = 0;
- c >>= 32; // signed shift
- }
- assert c == 0L : c; // borrow out of subtract
- assert dataInRangeIsZero(i, m, other); // negative result of subtract
- return new OldFDBigIntForTest( r, n-nzeros );
- }
-
- private static boolean dataInRangeIsZero(int i, int m, OldFDBigIntForTest other) {
- while ( i < m )
- if (other.data[i++] != 0)
- return false;
- return true;
- }
-
- /*
- * Compare OldFDBigIntForTest with another OldFDBigIntForTest. Return an integer
- * >0: this > other
- * 0: this == other
- * <0: this < other
- */
- public int
- cmp( OldFDBigIntForTest other ){
- int i;
- if ( this.nWords > other.nWords ){
- // if any of my high-order words is non-zero,
- // then the answer is evident
- int j = other.nWords-1;
- for ( i = this.nWords-1; i > j ; i-- )
- if ( this.data[i] != 0 ) return 1;
- }else if ( this.nWords < other.nWords ){
- // if any of other's high-order words is non-zero,
- // then the answer is evident
- int j = this.nWords-1;
- for ( i = other.nWords-1; i > j ; i-- )
- if ( other.data[i] != 0 ) return -1;
- } else{
- i = this.nWords-1;
- }
- for ( ; i > 0 ; i-- )
- if ( this.data[i] != other.data[i] )
- break;
- // careful! want unsigned compare!
- // use brute force here.
- int a = this.data[i];
- int b = other.data[i];
- if ( a < 0 ){
- // a is really big, unsigned
- if ( b < 0 ){
- return a-b; // both big, negative
- } else {
- return 1; // b not big, answer is obvious;
- }
- } else {
- // a is not really big
- if ( b < 0 ) {
- // but b is really big
- return -1;
- } else {
- return a - b;
- }
- }
- }
-
- /*
- * Compute
- * q = (int)( this / S )
- * this = 10 * ( this mod S )
- * Return q.
- * This is the iteration step of digit development for output.
- * We assume that S has been normalized, as above, and that
- * "this" has been lshift'ed accordingly.
- * Also assume, of course, that the result, q, can be expressed
- * as an integer, 0 <= q < 10.
- */
- public int
- quoRemIteration( OldFDBigIntForTest S )throws IllegalArgumentException {
- // ensure that this and S have the same number of
- // digits. If S is properly normalized and q < 10 then
- // this must be so.
- if ( nWords != S.nWords ){
- throw new IllegalArgumentException("disparate values");
- }
- // estimate q the obvious way. We will usually be
- // right. If not, then we're only off by a little and
- // will re-add.
- int n = nWords-1;
- long q = ((long)data[n]&0xffffffffL) / (long)S.data[n];
- long diff = 0L;
- for ( int i = 0; i <= n ; i++ ){
- diff += ((long)data[i]&0xffffffffL) - q*((long)S.data[i]&0xffffffffL);
- data[i] = (int)diff;
- diff >>= 32; // N.B. SIGNED shift.
- }
- if ( diff != 0L ) {
- // damn, damn, damn. q is too big.
- // add S back in until this turns +. This should
- // not be very many times!
- long sum = 0L;
- while ( sum == 0L ){
- sum = 0L;
- for ( int i = 0; i <= n; i++ ){
- sum += ((long)data[i]&0xffffffffL) + ((long)S.data[i]&0xffffffffL);
- data[i] = (int) sum;
- sum >>= 32; // Signed or unsigned, answer is 0 or 1
- }
- /*
- * Originally the following line read
- * "if ( sum !=0 && sum != -1 )"
- * but that would be wrong, because of the
- * treatment of the two values as entirely unsigned,
- * it would be impossible for a carry-out to be interpreted
- * as -1 -- it would have to be a single-bit carry-out, or
- * +1.
- */
- assert sum == 0 || sum == 1 : sum; // carry out of division correction
- q -= 1;
- }
- }
- // finally, we can multiply this by 10.
- // it cannot overflow, right, as the high-order word has
- // at least 4 high-order zeros!
- long p = 0L;
- for ( int i = 0; i <= n; i++ ){
- p += 10*((long)data[i]&0xffffffffL);
- data[i] = (int)p;
- p >>= 32; // SIGNED shift.
- }
- assert p == 0L : p; // Carry out of *10
- return (int)q;
- }
-
- public long
- longValue(){
- // if this can be represented as a long, return the value
- assert this.nWords > 0 : this.nWords; // longValue confused
-
- if (this.nWords == 1)
- return ((long)data[0]&0xffffffffL);
-
- assert dataInRangeIsZero(2, this.nWords, this); // value too big
- assert data[1] >= 0; // value too big
- return ((long)(data[1]) << 32) | ((long)data[0]&0xffffffffL);
- }
-
- public String
- toString() {
- StringBuffer r = new StringBuffer(30);
- r.append('[');
- int i = Math.min( nWords-1, data.length-1) ;
- if ( nWords > data.length ){
- r.append( "("+data.length+"<"+nWords+"!)" );
- }
- for( ; i> 0 ; i-- ){
- r.append( Integer.toHexString( data[i] ) );
- r.append(' ');
- }
- r.append( Integer.toHexString( data[0] ) );
- r.append(']');
- return new String( r );
- }
-}
--- a/jdk/test/sun/misc/FloatingDecimal/OldFloatingDecimalForTest.java Tue Dec 22 11:07:17 2015 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2434 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-//package sun.misc;
-
-import java.util.regex.*;
-
-public class OldFloatingDecimalForTest{
- boolean isExceptional;
- boolean isNegative;
- int decExponent;
- char digits[];
- int nDigits;
- int bigIntExp;
- int bigIntNBits;
- boolean mustSetRoundDir = false;
- boolean fromHex = false;
- int roundDir = 0; // set by doubleValue
-
- /*
- * The fields below provides additional information about the result of
- * the binary to decimal digits conversion done in dtoa() and roundup()
- * methods. They are changed if needed by those two methods.
- */
-
- // True if the dtoa() binary to decimal conversion was exact.
- boolean exactDecimalConversion = false;
-
- // True if the result of the binary to decimal conversion was rounded-up
- // at the end of the conversion process, i.e. roundUp() method was called.
- boolean decimalDigitsRoundedUp = false;
-
- private OldFloatingDecimalForTest( boolean negSign, int decExponent, char []digits, int n, boolean e )
- {
- isNegative = negSign;
- isExceptional = e;
- this.decExponent = decExponent;
- this.digits = digits;
- this.nDigits = n;
- }
-
- /*
- * Constants of the implementation
- * Most are IEEE-754 related.
- * (There are more really boring constants at the end.)
- */
- static final long signMask = 0x8000000000000000L;
- static final long expMask = 0x7ff0000000000000L;
- static final long fractMask= ~(signMask|expMask);
- static final int expShift = 52;
- static final int expBias = 1023;
- static final long fractHOB = ( 1L<<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 OldFDBigIntForTest b5p[];
-
- private static synchronized OldFDBigIntForTest
- big5pow( int p ){
- assert p >= 0 : p; // negative power of 5
- if ( b5p == null ){
- b5p = new OldFDBigIntForTest[ p+1 ];
- }else if (b5p.length <= p ){
- OldFDBigIntForTest t[] = new OldFDBigIntForTest[ p+1 ];
- System.arraycopy( b5p, 0, t, 0, b5p.length );
- b5p = t;
- }
- if ( b5p[p] != null )
- return b5p[p];
- else if ( p < small5pow.length )
- return b5p[p] = new OldFDBigIntForTest( small5pow[p] );
- else if ( p < long5pow.length )
- return b5p[p] = new OldFDBigIntForTest( long5pow[p] );
- else {
- // construct the value.
- // recursively.
- int q, r;
- // in order to compute 5^p,
- // compute its square root, 5^(p/2) and square.
- // or, let q = p / 2, r = p -q, then
- // 5^p = 5^(q+r) = 5^q * 5^r
- q = p >> 1;
- r = p - q;
- OldFDBigIntForTest bigq = b5p[q];
- if ( bigq == null )
- bigq = big5pow ( q );
- if ( r < small5pow.length ){
- return (b5p[p] = bigq.mult( small5pow[r] ) );
- }else{
- OldFDBigIntForTest bigr = b5p[ r ];
- if ( bigr == null )
- bigr = big5pow( r );
- return (b5p[p] = bigq.mult( bigr ) );
- }
- }
- }
-
- //
- // a common operation
- //
- private static OldFDBigIntForTest
- multPow52( OldFDBigIntForTest v, int p5, int p2 ){
- if ( p5 != 0 ){
- if ( p5 < small5pow.length ){
- v = v.mult( small5pow[p5] );
- } else {
- v = v.mult( big5pow( p5 ) );
- }
- }
- if ( p2 != 0 ){
- v.lshiftMe( p2 );
- }
- return v;
- }
-
- //
- // another common operation
- //
- private static OldFDBigIntForTest
- constructPow52( int p5, int p2 ){
- OldFDBigIntForTest v = new OldFDBigIntForTest( big5pow( p5 ) );
- if ( p2 != 0 ){
- v.lshiftMe( p2 );
- }
- return v;
- }
-
- /*
- * Make a floating double into a OldFDBigIntForTest.
- * This could also be structured as a OldFDBigIntForTest
- * constructor, but we'd have to build a lot of knowledge
- * about floating-point representation into it, and we don't want to.
- *
- * AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
- * bigIntExp and bigIntNBits
- *
- */
- private OldFDBigIntForTest
- doubleToBigInt( double dval ){
- long lbits = Double.doubleToLongBits( dval ) & ~signMask;
- int binexp = (int)(lbits >>> expShift);
- lbits &= fractMask;
- if ( binexp > 0 ){
- lbits |= fractHOB;
- } else {
- assert lbits != 0L : lbits; // doubleToBigInt(0.0)
- binexp +=1;
- while ( (lbits & fractHOB ) == 0L){
- lbits <<= 1;
- binexp -= 1;
- }
- }
- binexp -= expBias;
- int nbits = countBits( lbits );
- /*
- * We now know where the high-order 1 bit is,
- * and we know how many there are.
- */
- int lowOrderZeros = expShift+1-nbits;
- lbits >>>= lowOrderZeros;
-
- bigIntExp = binexp+1-nbits;
- bigIntNBits = nbits;
- return new OldFDBigIntForTest( lbits );
- }
-
- /*
- * Compute a number that is the ULP of the given value,
- * for purposes of addition/subtraction. Generally easy.
- * More difficult if subtracting and the argument
- * is a normalized a power of 2, as the ULP changes at these points.
- */
- private static double ulp( double dval, boolean subtracting ){
- long lbits = Double.doubleToLongBits( dval ) & ~signMask;
- int binexp = (int)(lbits >>> expShift);
- double ulpval;
- if ( subtracting && ( binexp >= expShift ) && ((lbits&fractMask) == 0L) ){
- // for subtraction from normalized, powers of 2,
- // use next-smaller exponent
- binexp -= 1;
- }
- if ( binexp > expShift ){
- ulpval = Double.longBitsToDouble( ((long)(binexp-expShift))<<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);
- decimalDigitsRoundedUp = true;
- }
-
- public boolean digitsRoundedUp() {
- return decimalDigitsRoundedUp;
- }
-
- /*
- * FIRST IMPORTANT CONSTRUCTOR: DOUBLE
- */
- public OldFloatingDecimalForTest( double d )
- {
- long dBits = Double.doubleToLongBits( d );
- long fractBits;
- int binExp;
- int nSignificantBits;
-
- // discover and delete sign
- if ( (dBits&signMask) != 0 ){
- isNegative = true;
- dBits ^= signMask;
- } else {
- isNegative = false;
- }
- // Begin to unpack
- // Discover obvious special cases of NaN and Infinity.
- binExp = (int)( (dBits&expMask) >> expShift );
- fractBits = dBits&fractMask;
- if ( binExp == (int)(expMask>>expShift) ) {
- isExceptional = true;
- if ( fractBits == 0L ){
- digits = infinity;
- } else {
- digits = notANumber;
- isNegative = false; // NaN has no sign!
- }
- nDigits = digits.length;
- return;
- }
- isExceptional = false;
- // Finish unpacking
- // Normalize denormalized numbers.
- // Insert assumed high-order bit for normalized numbers.
- // Subtract exponent bias.
- if ( binExp == 0 ){
- if ( fractBits == 0L ){
- // not a denorm, just a 0!
- decExponent = 0;
- digits = zero;
- nDigits = 1;
- return;
- }
- while ( (fractBits&fractHOB) == 0L ){
- fractBits <<= 1;
- binExp -= 1;
- }
- nSignificantBits = expShift + binExp +1; // recall binExp is - shift count.
- binExp += 1;
- } else {
- fractBits |= fractHOB;
- nSignificantBits = expShift+1;
- }
- binExp -= expBias;
- // call the routine that actually does all the hard work.
- dtoa( binExp, fractBits, nSignificantBits );
- }
-
- /*
- * SECOND IMPORTANT CONSTRUCTOR: SINGLE
- */
- public OldFloatingDecimalForTest( float f )
- {
- int fBits = Float.floatToIntBits( f );
- int fractBits;
- int binExp;
- int nSignificantBits;
-
- // discover and delete sign
- if ( (fBits&singleSignMask) != 0 ){
- isNegative = true;
- fBits ^= singleSignMask;
- } else {
- isNegative = false;
- }
- // Begin to unpack
- // Discover obvious special cases of NaN and Infinity.
- binExp = (fBits&singleExpMask) >> singleExpShift;
- fractBits = fBits&singleFractMask;
- if ( binExp == (singleExpMask>>singleExpShift) ) {
- isExceptional = true;
- if ( fractBits == 0L ){
- digits = infinity;
- } else {
- digits = notANumber;
- isNegative = false; // NaN has no sign!
- }
- nDigits = digits.length;
- return;
- }
- isExceptional = false;
- // Finish unpacking
- // Normalize denormalized numbers.
- // Insert assumed high-order bit for normalized numbers.
- // Subtract exponent bias.
- if ( binExp == 0 ){
- if ( fractBits == 0 ){
- // not a denorm, just a 0!
- decExponent = 0;
- digits = zero;
- nDigits = 1;
- return;
- }
- while ( (fractBits&singleFractHOB) == 0 ){
- fractBits <<= 1;
- binExp -= 1;
- }
- nSignificantBits = singleExpShift + binExp +1; // recall binExp is - shift count.
- binExp += 1;
- } else {
- fractBits |= singleFractHOB;
- nSignificantBits = singleExpShift+1;
- }
- binExp -= singleExpBias;
- // call the routine that actually does all the hard work.
- dtoa( binExp, ((long)fractBits)<<(expShift-singleExpShift), nSignificantBits );
- }
-
- private void
- dtoa( int binExp, long fractBits, int nSignificantBits )
- {
- int nFractBits; // number of significant bits of fractBits;
- int nTinyBits; // number of these to the right of the point.
- int decExp;
-
- // Examine number. Determine if it is an easy case,
- // which we can do pretty trivially using float/long conversion,
- // or whether we must do real work.
- nFractBits = countBits( fractBits );
- nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
- if ( binExp <= maxSmallBinExp && binExp >= minSmallBinExp ){
- // Look more closely at the number to decide if,
- // with scaling by 10^nTinyBits, the result will fit in
- // a long.
- if ( (nTinyBits < long5pow.length) && ((nFractBits + n5bits[nTinyBits]) < 64 ) ){
- /*
- * We can do this:
- * take the fraction bits, which are normalized.
- * (a) nTinyBits == 0: Shift left or right appropriately
- * to align the binary point at the extreme right, i.e.
- * where a long int point is expected to be. The integer
- * result is easily converted to a string.
- * (b) nTinyBits > 0: Shift right by expShift-nFractBits,
- * which effectively converts to long and scales by
- * 2^nTinyBits. Then multiply by 5^nTinyBits to
- * complete the scaling. We know this won't overflow
- * because we just counted the number of bits necessary
- * in the result. The integer you get from this can
- * then be converted to a string pretty easily.
- */
- long halfULP;
- if ( nTinyBits == 0 ) {
- if ( binExp > nSignificantBits ){
- halfULP = 1L << ( binExp-nSignificantBits-1);
- } else {
- halfULP = 0L;
- }
- if ( binExp >= expShift ){
- fractBits <<= (binExp-expShift);
- } else {
- fractBits >>>= (expShift-binExp) ;
- }
- developLongDigits( 0, fractBits, halfULP );
- return;
- }
- /*
- * The following causes excess digits to be printed
- * out in the single-float case. Our manipulation of
- * halfULP here is apparently not correct. If we
- * better understand how this works, perhaps we can
- * use this special case again. But for the time being,
- * we do not.
- * else {
- * fractBits >>>= expShift+1-nFractBits;
- * fractBits *= long5pow[ nTinyBits ];
- * halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
- * developLongDigits( -nTinyBits, fractBits, halfULP );
- * return;
- * }
- */
- }
- }
- /*
- * This is the hard case. We are going to compute large positive
- * integers B and S and integer decExp, s.t.
- * d = ( B / S ) * 10^decExp
- * 1 <= B / S < 10
- * Obvious choices are:
- * decExp = floor( log10(d) )
- * B = d * 2^nTinyBits * 10^max( 0, -decExp )
- * S = 10^max( 0, decExp) * 2^nTinyBits
- * (noting that nTinyBits has already been forced to non-negative)
- * I am also going to compute a large positive integer
- * M = (1/2^nSignificantBits) * 2^nTinyBits * 10^max( 0, -decExp )
- * i.e. M is (1/2) of the ULP of d, scaled like B.
- * When we iterate through dividing B/S and picking off the
- * quotient bits, we will know when to stop when the remainder
- * is <= M.
- *
- * We keep track of powers of 2 and powers of 5.
- */
-
- /*
- * Estimate decimal exponent. (If it is small-ish,
- * we could double-check.)
- *
- * First, scale the mantissa bits such that 1 <= d2 < 2.
- * We are then going to estimate
- * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5)
- * and so we can estimate
- * log10(d) ~=~ log10(d2) + binExp * log10(2)
- * take the floor and call it decExp.
- * FIXME -- use more precise constants here. It costs no more.
- */
- double d2 = Double.longBitsToDouble(
- expOne | ( fractBits &~ fractHOB ) );
- decExp = (int)Math.floor(
- (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981 );
- int B2, B5; // powers of 2 and powers of 5, respectively, in B
- int S2, S5; // powers of 2 and powers of 5, respectively, in S
- int M2, M5; // powers of 2 and powers of 5, respectively, in M
- int Bbits; // binary digits needed to represent B, approx.
- int tenSbits; // binary digits needed to represent 10*S, approx.
- OldFDBigIntForTest Sval, Bval, Mval;
-
- B5 = Math.max( 0, -decExp );
- B2 = B5 + nTinyBits + binExp;
-
- S5 = Math.max( 0, decExp );
- S2 = S5 + nTinyBits;
-
- M5 = B5;
- M2 = B2 - nSignificantBits;
-
- /*
- * the long integer fractBits contains the (nFractBits) interesting
- * bits from the mantissa of d ( hidden 1 added if necessary) followed
- * by (expShift+1-nFractBits) zeros. In the interest of compactness,
- * I will shift out those zeros before turning fractBits into a
- * OldFDBigIntForTest. The resulting whole number will be
- * d * 2^(nFractBits-1-binExp).
- */
- fractBits >>>= (expShift+1-nFractBits);
- B2 -= nFractBits-1;
- int common2factor = Math.min( B2, S2 );
- B2 -= common2factor;
- S2 -= common2factor;
- M2 -= common2factor;
-
- /*
- * HACK!! For exact powers of two, the next smallest number
- * is only half as far away as we think (because the meaning of
- * ULP changes at power-of-two bounds) for this reason, we
- * hack M2. Hope this works.
- */
- if ( nFractBits == 1 )
- M2 -= 1;
-
- if ( M2 < 0 ){
- // oops.
- // since we cannot scale M down far enough,
- // we must scale the other values up.
- B2 -= M2;
- S2 -= M2;
- M2 = 0;
- }
- /*
- * Construct, Scale, iterate.
- * Some day, we'll write a stopping test that takes
- * account of the asymmetry of the spacing of floating-point
- * numbers below perfect powers of 2
- * 26 Sept 96 is not that day.
- * So we use a symmetric test.
- */
- char digits[] = this.digits = new char[18];
- int ndigit = 0;
- boolean low, high;
- long lowDigitDifference;
- int q;
-
- /*
- * Detect the special cases where all the numbers we are about
- * to compute will fit in int or long integers.
- * In these cases, we will avoid doing OldFDBigIntForTest arithmetic.
- * We use the same algorithms, except that we "normalize"
- * our OldFDBigIntForTests before iterating. This is to make division easier,
- * as it makes our fist guess (quotient of high-order words)
- * more accurate!
- *
- * Some day, we'll write a stopping test that takes
- * account of the asymmetry of the spacing of floating-point
- * numbers below perfect powers of 2
- * 26 Sept 96 is not that day.
- * So we use a symmetric test.
- */
- Bbits = nFractBits + B2 + (( B5 < n5bits.length )? n5bits[B5] : ( B5*3 ));
- tenSbits = S2+1 + (( (S5+1) < n5bits.length )? n5bits[(S5+1)] : ( (S5+1)*3 ));
- if ( Bbits < 64 && tenSbits < 64){
- if ( Bbits < 32 && tenSbits < 32){
- // wa-hoo! They're all ints!
- int b = ((int)fractBits * small5pow[B5] ) << B2;
- int s = small5pow[S5] << S2;
- int m = small5pow[M5] << M2;
- int tens = s * 10;
- /*
- * Unroll the first iteration. If our decExp estimate
- * was too high, our first quotient will be zero. In this
- * case, we discard it and decrement decExp.
- */
- ndigit = 0;
- q = b / s;
- b = 10 * ( b % s );
- m *= 10;
- low = (b < m );
- high = (b+m > tens );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- /*
- * HACK! Java spec sez that we always have at least
- * one digit after the . in either F- or E-form output.
- * Thus we will need more than one digit if we're using
- * E-form
- */
- if ( decExp < -3 || decExp >= 8 ){
- high = low = false;
- }
- while( ! low && ! high ){
- q = b / s;
- b = 10 * ( b % s );
- m *= 10;
- assert q < 10 : q; // excessively large digit
- if ( m > 0L ){
- low = (b < m );
- high = (b+m > tens );
- } else {
- // hack -- m might overflow!
- // in this case, it is certainly > b,
- // which won't
- // and b+m > tens, too, since that has overflowed
- // either!
- low = true;
- high = true;
- }
- digits[ndigit++] = (char)('0' + q);
- }
- lowDigitDifference = (b<<1) - tens;
- exactDecimalConversion = (b == 0);
- } else {
- // still good! they're all longs!
- long b = (fractBits * long5pow[B5] ) << B2;
- long s = long5pow[S5] << S2;
- long m = long5pow[M5] << M2;
- long tens = s * 10L;
- /*
- * Unroll the first iteration. If our decExp estimate
- * was too high, our first quotient will be zero. In this
- * case, we discard it and decrement decExp.
- */
- ndigit = 0;
- q = (int) ( b / s );
- b = 10L * ( b % s );
- m *= 10L;
- low = (b < m );
- high = (b+m > tens );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- /*
- * HACK! Java spec sez that we always have at least
- * one digit after the . in either F- or E-form output.
- * Thus we will need more than one digit if we're using
- * E-form
- */
- if ( decExp < -3 || decExp >= 8 ){
- high = low = false;
- }
- while( ! low && ! high ){
- q = (int) ( b / s );
- b = 10 * ( b % s );
- m *= 10;
- assert q < 10 : q; // excessively large digit
- if ( m > 0L ){
- low = (b < m );
- high = (b+m > tens );
- } else {
- // hack -- m might overflow!
- // in this case, it is certainly > b,
- // which won't
- // and b+m > tens, too, since that has overflowed
- // either!
- low = true;
- high = true;
- }
- digits[ndigit++] = (char)('0' + q);
- }
- lowDigitDifference = (b<<1) - tens;
- exactDecimalConversion = (b == 0);
- }
- } else {
- OldFDBigIntForTest ZeroVal = new OldFDBigIntForTest(0);
- OldFDBigIntForTest tenSval;
- int shiftBias;
-
- /*
- * We really must do OldFDBigIntForTest arithmetic.
- * Fist, construct our OldFDBigIntForTest initial values.
- */
- Bval = multPow52( new OldFDBigIntForTest( fractBits ), B5, B2 );
- Sval = constructPow52( S5, S2 );
- Mval = constructPow52( M5, M2 );
-
-
- // normalize so that division works better
- Bval.lshiftMe( shiftBias = Sval.normalizeMe() );
- Mval.lshiftMe( shiftBias );
- tenSval = Sval.mult( 10 );
- /*
- * Unroll the first iteration. If our decExp estimate
- * was too high, our first quotient will be zero. In this
- * case, we discard it and decrement decExp.
- */
- ndigit = 0;
- q = Bval.quoRemIteration( Sval );
- Mval = Mval.mult( 10 );
- low = (Bval.cmp( Mval ) < 0);
- high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- /*
- * HACK! Java spec sez that we always have at least
- * one digit after the . in either F- or E-form output.
- * Thus we will need more than one digit if we're using
- * E-form
- */
- if ( decExp < -3 || decExp >= 8 ){
- high = low = false;
- }
- while( ! low && ! high ){
- q = Bval.quoRemIteration( Sval );
- Mval = Mval.mult( 10 );
- assert q < 10 : q; // excessively large digit
- low = (Bval.cmp( Mval ) < 0);
- high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
- digits[ndigit++] = (char)('0' + q);
- }
- if ( high && low ){
- Bval.lshiftMe(1);
- lowDigitDifference = Bval.cmp(tenSval);
- } else {
- lowDigitDifference = 0L; // this here only for flow analysis!
- }
- exactDecimalConversion = (Bval.cmp( ZeroVal ) == 0);
- }
- this.decExponent = decExp+1;
- this.digits = digits;
- this.nDigits = ndigit;
- /*
- * Last digit gets rounded based on stopping condition.
- */
- if ( high ){
- if ( low ){
- if ( lowDigitDifference == 0L ){
- // it's a tie!
- // choose based on which digits we like.
- if ( (digits[nDigits-1]&1) != 0 ) roundup();
- } else if ( lowDigitDifference > 0 ){
- roundup();
- }
- } else {
- roundup();
- }
- }
- }
-
- public boolean decimalDigitsExact() {
- return exactDecimalConversion;
- }
-
- public String
- toString(){
- // most brain-dead version
- StringBuffer result = new StringBuffer( nDigits+8 );
- if ( isNegative ){ result.append( '-' ); }
- if ( isExceptional ){
- result.append( digits, 0, nDigits );
- } else {
- result.append( "0.");
- result.append( digits, 0, nDigits );
- result.append('e');
- result.append( decExponent );
- }
- return new String(result);
- }
-
- public String toJavaFormatString() {
- char result[] = perThreadBuffer.get();
- int i = getChars(result);
- return new String(result, 0, i);
- }
-
- private int getChars(char[] result) {
- assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
- int i = 0;
- if (isNegative) { result[0] = '-'; i = 1; }
- if (isExceptional) {
- System.arraycopy(digits, 0, result, i, nDigits);
- i += nDigits;
- } else {
- if (decExponent > 0 && decExponent < 8) {
- // print digits.digits.
- int charLength = Math.min(nDigits, decExponent);
- System.arraycopy(digits, 0, result, i, charLength);
- i += charLength;
- if (charLength < decExponent) {
- charLength = decExponent-charLength;
- System.arraycopy(zero, 0, result, i, charLength);
- i += charLength;
- result[i++] = '.';
- result[i++] = '0';
- } else {
- result[i++] = '.';
- if (charLength < nDigits) {
- int t = nDigits - charLength;
- System.arraycopy(digits, charLength, result, i, t);
- i += t;
- } else {
- result[i++] = '0';
- }
- }
- } else if (decExponent <=0 && decExponent > -3) {
- result[i++] = '0';
- result[i++] = '.';
- if (decExponent != 0) {
- System.arraycopy(zero, 0, result, i, -decExponent);
- i -= decExponent;
- }
- System.arraycopy(digits, 0, result, i, nDigits);
- i += nDigits;
- } else {
- result[i++] = digits[0];
- result[i++] = '.';
- if (nDigits > 1) {
- System.arraycopy(digits, 1, result, i, nDigits-1);
- i += nDigits-1;
- } else {
- result[i++] = '0';
- }
- result[i++] = 'E';
- int e;
- if (decExponent <= 0) {
- result[i++] = '-';
- e = -decExponent+1;
- } else {
- e = decExponent-1;
- }
- // decExponent has 1, 2, or 3, digits
- if (e <= 9) {
- result[i++] = (char)(e+'0');
- } else if (e <= 99) {
- result[i++] = (char)(e/10 +'0');
- result[i++] = (char)(e%10 + '0');
- } else {
- result[i++] = (char)(e/100+'0');
- e %= 100;
- result[i++] = (char)(e/10+'0');
- result[i++] = (char)(e%10 + '0');
- }
- }
- }
- return i;
- }
-
- // Per-thread buffer for string/stringbuffer conversion
- private static ThreadLocal<char[]> perThreadBuffer = new ThreadLocal<char[]>() {
- protected synchronized char[] initialValue() {
- return new char[26];
- }
- };
-
- public void appendTo(Appendable buf) {
- char result[] = perThreadBuffer.get();
- int i = getChars(result);
- if (buf instanceof StringBuilder)
- ((StringBuilder) buf).append(result, 0, i);
- else if (buf instanceof StringBuffer)
- ((StringBuffer) buf).append(result, 0, i);
- else
- assert false;
- }
-
- @SuppressWarnings("fallthrough")
- public static OldFloatingDecimalForTest
- readJavaFormatString( String in ) throws NumberFormatException {
- boolean isNegative = false;
- boolean signSeen = false;
- int decExp;
- char c;
-
- parseNumber:
- try{
- in = in.trim(); // don't fool around with white space.
- // throws NullPointerException if null
- int l = in.length();
- if ( l == 0 ) throw new NumberFormatException("empty String");
- int i = 0;
- switch ( c = in.charAt( i ) ){
- case '-':
- isNegative = true;
- //FALLTHROUGH
- case '+':
- i++;
- signSeen = true;
- }
-
- // Check for NaN and Infinity strings
- c = in.charAt(i);
- if(c == 'N' || c == 'I') { // possible NaN or infinity
- boolean potentialNaN = false;
- char targetChars[] = null; // char array of "NaN" or "Infinity"
-
- if(c == 'N') {
- targetChars = notANumber;
- potentialNaN = true;
- } else {
- targetChars = infinity;
- }
-
- // compare Input string to "NaN" or "Infinity"
- int j = 0;
- while(i < l && j < targetChars.length) {
- if(in.charAt(i) == targetChars[j]) {
- i++; j++;
- }
- else // something is amiss, throw exception
- break parseNumber;
- }
-
- // For the candidate string to be a NaN or infinity,
- // all characters in input string and target char[]
- // must be matched ==> j must equal targetChars.length
- // and i must equal l
- if( (j == targetChars.length) && (i == l) ) { // return NaN or infinity
- return (potentialNaN ? new OldFloatingDecimalForTest(Double.NaN) // NaN has no sign
- : new OldFloatingDecimalForTest(isNegative?
- Double.NEGATIVE_INFINITY:
- Double.POSITIVE_INFINITY)) ;
- }
- else { // something went wrong, throw exception
- break parseNumber;
- }
-
- } else if (c == '0') { // check for hexadecimal floating-point number
- if (l > i+1 ) {
- char ch = in.charAt(i+1);
- if (ch == 'x' || ch == 'X' ) // possible hex string
- return parseHexString(in);
- }
- } // look for and process decimal floating-point string
-
- char[] digits = new char[ l ];
- int nDigits= 0;
- boolean decSeen = false;
- int decPt = 0;
- int nLeadZero = 0;
- int nTrailZero= 0;
- digitLoop:
- while ( i < l ){
- switch ( c = in.charAt( i ) ){
- case '0':
- if ( nDigits > 0 ){
- nTrailZero += 1;
- } else {
- nLeadZero += 1;
- }
- break; // out of switch.
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- while ( nTrailZero > 0 ){
- digits[nDigits++] = '0';
- nTrailZero -= 1;
- }
- digits[nDigits++] = c;
- break; // out of switch.
- case '.':
- if ( decSeen ){
- // already saw one ., this is the 2nd.
- throw new NumberFormatException("multiple points");
- }
- decPt = i;
- if ( signSeen ){
- decPt -= 1;
- }
- decSeen = true;
- break; // out of switch.
- default:
- break digitLoop;
- }
- i++;
- }
- /*
- * At this point, we've scanned all the digits and decimal
- * point we're going to see. Trim off leading and trailing
- * zeros, which will just confuse us later, and adjust
- * our initial decimal exponent accordingly.
- * To review:
- * we have seen i total characters.
- * nLeadZero of them were zeros before any other digits.
- * nTrailZero of them were zeros after any other digits.
- * if ( decSeen ), then a . was seen after decPt characters
- * ( including leading zeros which have been discarded )
- * nDigits characters were neither lead nor trailing
- * zeros, nor point
- */
- /*
- * special hack: if we saw no non-zero digits, then the
- * answer is zero!
- * Unfortunately, we feel honor-bound to keep parsing!
- */
- if ( nDigits == 0 ){
- digits = zero;
- nDigits = 1;
- if ( nLeadZero == 0 ){
- // we saw NO DIGITS AT ALL,
- // not even a crummy 0!
- // this is not allowed.
- break parseNumber; // go throw exception
- }
-
- }
-
- /* Our initial exponent is decPt, adjusted by the number of
- * discarded zeros. Or, if there was no decPt,
- * then its just nDigits adjusted by discarded trailing zeros.
- */
- if ( decSeen ){
- decExp = decPt - nLeadZero;
- } else {
- decExp = nDigits+nTrailZero;
- }
-
- /*
- * Look for 'e' or 'E' and an optionally signed integer.
- */
- if ( (i < l) && (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
- int expSign = 1;
- int expVal = 0;
- int reallyBig = Integer.MAX_VALUE / 10;
- boolean expOverflow = false;
- switch( in.charAt(++i) ){
- case '-':
- expSign = -1;
- //FALLTHROUGH
- case '+':
- i++;
- }
- int expAt = i;
- expLoop:
- while ( i < l ){
- if ( expVal >= reallyBig ){
- // the next character will cause integer
- // overflow.
- expOverflow = true;
- }
- switch ( c = in.charAt(i++) ){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- expVal = expVal*10 + ( (int)c - (int)'0' );
- continue;
- default:
- i--; // back up.
- break expLoop; // stop parsing exponent.
- }
- }
- int expLimit = bigDecimalExponent+nDigits+nTrailZero;
- if ( expOverflow || ( expVal > expLimit ) ){
- //
- // The intent here is to end up with
- // infinity or zero, as appropriate.
- // The reason for yielding such a small decExponent,
- // rather than something intuitive such as
- // expSign*Integer.MAX_VALUE, is that this value
- // is subject to further manipulation in
- // doubleValue() and floatValue(), and I don't want
- // it to be able to cause overflow there!
- // (The only way we can get into trouble here is for
- // really outrageous nDigits+nTrailZero, such as 2 billion. )
- //
- decExp = expSign*expLimit;
- } else {
- // this should not overflow, since we tested
- // for expVal > (MAX+N), where N >= abs(decExp)
- decExp = decExp + expSign*expVal;
- }
-
- // if we saw something not a digit ( or end of string )
- // after the [Ee][+-], without seeing any digits at all
- // this is certainly an error. If we saw some digits,
- // but then some trailing garbage, that might be ok.
- // so we just fall through in that case.
- // HUMBUG
- if ( i == expAt )
- break parseNumber; // certainly bad
- }
- /*
- * We parsed everything we could.
- * If there are leftovers, then this is not good input!
- */
- if ( i < l &&
- ((i != l - 1) ||
- (in.charAt(i) != 'f' &&
- in.charAt(i) != 'F' &&
- in.charAt(i) != 'd' &&
- in.charAt(i) != 'D'))) {
- break parseNumber; // go throw exception
- }
-
- return new OldFloatingDecimalForTest( isNegative, decExp, digits, nDigits, false );
- } catch ( StringIndexOutOfBoundsException e ){ }
- throw new NumberFormatException("For input string: \"" + in + "\"");
- }
-
- /*
- * Take a FloatingDecimal, which we presumably just scanned in,
- * and find out what its value is, as a double.
- *
- * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
- * ROUNDING DIRECTION in case the result is really destined
- * for a single-precision float.
- */
-
- public strictfp double doubleValue(){
- int kDigits = Math.min( nDigits, maxDecimalDigits+1 );
- long lValue;
- double dValue;
- double rValue, tValue;
-
- // First, check for NaN and Infinity values
- if(digits == infinity || digits == notANumber) {
- if(digits == notANumber)
- return Double.NaN;
- else
- return (isNegative?Double.NEGATIVE_INFINITY:Double.POSITIVE_INFINITY);
- }
- else {
- if (mustSetRoundDir) {
- roundDir = 0;
- }
- /*
- * convert the lead kDigits to a long integer.
- */
- // (special performance hack: start to do it using int)
- int iValue = (int)digits[0]-(int)'0';
- int iDigits = Math.min( kDigits, intDecimalDigits );
- for ( int i=1; i < iDigits; i++ ){
- iValue = iValue*10 + (int)digits[i]-(int)'0';
- }
- lValue = (long)iValue;
- for ( int i=iDigits; i < kDigits; i++ ){
- lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
- }
- dValue = (double)lValue;
- int exp = decExponent-kDigits;
- /*
- * lValue now contains a long integer with the value of
- * the first kDigits digits of the number.
- * dValue contains the (double) of the same.
- */
-
- if ( nDigits <= maxDecimalDigits ){
- /*
- * possibly an easy case.
- * We know that the digits can be represented
- * exactly. And if the exponent isn't too outrageous,
- * the whole thing can be done with one operation,
- * thus one rounding error.
- * Note that all our constructors trim all leading and
- * trailing zeros, so simple values (including zero)
- * will always end up here
- */
- if (exp == 0 || dValue == 0.0)
- return (isNegative)? -dValue : dValue; // small floating integer
- else if ( exp >= 0 ){
- if ( exp <= maxSmallTen ){
- /*
- * Can get the answer with one operation,
- * thus one roundoff.
- */
- rValue = dValue * small10pow[exp];
- if ( mustSetRoundDir ){
- tValue = rValue / small10pow[exp];
- roundDir = ( tValue == dValue ) ? 0
- :( tValue < dValue ) ? 1
- : -1;
- }
- return (isNegative)? -rValue : rValue;
- }
- int slop = maxDecimalDigits - kDigits;
- if ( exp <= maxSmallTen+slop ){
- /*
- * We can multiply dValue by 10^(slop)
- * and it is still "small" and exact.
- * Then we can multiply by 10^(exp-slop)
- * with one rounding.
- */
- dValue *= small10pow[slop];
- rValue = dValue * small10pow[exp-slop];
-
- if ( mustSetRoundDir ){
- tValue = rValue / small10pow[exp-slop];
- roundDir = ( tValue == dValue ) ? 0
- :( tValue < dValue ) ? 1
- : -1;
- }
- return (isNegative)? -rValue : rValue;
- }
- /*
- * Else we have a hard case with a positive exp.
- */
- } else {
- if ( exp >= -maxSmallTen ){
- /*
- * Can get the answer in one division.
- */
- rValue = dValue / small10pow[-exp];
- tValue = rValue * small10pow[-exp];
- if ( mustSetRoundDir ){
- roundDir = ( tValue == dValue ) ? 0
- :( tValue < dValue ) ? 1
- : -1;
- }
- return (isNegative)? -rValue : rValue;
- }
- /*
- * Else we have a hard case with a negative exp.
- */
- }
- }
-
- /*
- * Harder cases:
- * The sum of digits plus exponent is greater than
- * what we think we can do with one error.
- *
- * Start by approximating the right answer by,
- * naively, scaling by powers of 10.
- */
- if ( exp > 0 ){
- if ( decExponent > maxDecimalExponent+1 ){
- /*
- * Lets face it. This is going to be
- * Infinity. Cut to the chase.
- */
- return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
- }
- if ( (exp&15) != 0 ){
- dValue *= small10pow[exp&15];
- }
- if ( (exp>>=4) != 0 ){
- int j;
- for( j = 0; exp > 1; j++, exp>>=1 ){
- if ( (exp&1)!=0)
- dValue *= big10pow[j];
- }
- /*
- * The reason for the weird exp > 1 condition
- * in the above loop was so that the last multiply
- * would get unrolled. We handle it here.
- * It could overflow.
- */
- double t = dValue * big10pow[j];
- if ( Double.isInfinite( t ) ){
- /*
- * It did overflow.
- * Look more closely at the result.
- * If the exponent is just one too large,
- * then use the maximum finite as our estimate
- * value. Else call the result infinity
- * and punt it.
- * ( I presume this could happen because
- * rounding forces the result here to be
- * an ULP or two larger than
- * Double.MAX_VALUE ).
- */
- t = dValue / 2.0;
- t *= big10pow[j];
- if ( Double.isInfinite( t ) ){
- return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
- }
- t = Double.MAX_VALUE;
- }
- dValue = t;
- }
- } else if ( exp < 0 ){
- exp = -exp;
- if ( decExponent < minDecimalExponent-1 ){
- /*
- * Lets face it. This is going to be
- * zero. Cut to the chase.
- */
- return (isNegative)? -0.0 : 0.0;
- }
- if ( (exp&15) != 0 ){
- dValue /= small10pow[exp&15];
- }
- if ( (exp>>=4) != 0 ){
- int j;
- for( j = 0; exp > 1; j++, exp>>=1 ){
- if ( (exp&1)!=0)
- dValue *= tiny10pow[j];
- }
- /*
- * The reason for the weird exp > 1 condition
- * in the above loop was so that the last multiply
- * would get unrolled. We handle it here.
- * It could underflow.
- */
- double t = dValue * tiny10pow[j];
- if ( t == 0.0 ){
- /*
- * It did underflow.
- * Look more closely at the result.
- * If the exponent is just one too small,
- * then use the minimum finite as our estimate
- * value. Else call the result 0.0
- * and punt it.
- * ( I presume this could happen because
- * rounding forces the result here to be
- * an ULP or two less than
- * Double.MIN_VALUE ).
- */
- t = dValue * 2.0;
- t *= tiny10pow[j];
- if ( t == 0.0 ){
- return (isNegative)? -0.0 : 0.0;
- }
- t = Double.MIN_VALUE;
- }
- dValue = t;
- }
- }
-
- /*
- * dValue is now approximately the result.
- * The hard part is adjusting it, by comparison
- * with OldFDBigIntForTest arithmetic.
- * Formulate the EXACT big-number result as
- * bigD0 * 10^exp
- */
- OldFDBigIntForTest bigD0 = new OldFDBigIntForTest( lValue, digits, kDigits, nDigits );
- exp = decExponent - nDigits;
-
- correctionLoop:
- while(true){
- /* AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
- * bigIntExp and bigIntNBits
- */
- OldFDBigIntForTest bigB = doubleToBigInt( dValue );
-
- /*
- * Scale bigD, bigB appropriately for
- * big-integer operations.
- * Naively, we multiply by powers of ten
- * and powers of two. What we actually do
- * is keep track of the powers of 5 and
- * powers of 2 we would use, then factor out
- * common divisors before doing the work.
- */
- int B2, B5; // powers of 2, 5 in bigB
- int D2, D5; // powers of 2, 5 in bigD
- int Ulp2; // powers of 2 in halfUlp.
- if ( exp >= 0 ){
- B2 = B5 = 0;
- D2 = D5 = exp;
- } else {
- B2 = B5 = -exp;
- D2 = D5 = 0;
- }
- if ( bigIntExp >= 0 ){
- B2 += bigIntExp;
- } else {
- D2 -= bigIntExp;
- }
- Ulp2 = B2;
- // shift bigB and bigD left by a number s. t.
- // halfUlp is still an integer.
- int hulpbias;
- if ( bigIntExp+bigIntNBits <= -expBias+1 ){
- // This is going to be a denormalized number
- // (if not actually zero).
- // half an ULP is at 2^-(expBias+expShift+1)
- hulpbias = bigIntExp+ expBias + expShift;
- } else {
- hulpbias = expShift + 2 - bigIntNBits;
- }
- B2 += hulpbias;
- D2 += hulpbias;
- // if there are common factors of 2, we might just as well
- // factor them out, as they add nothing useful.
- int common2 = Math.min( B2, Math.min( D2, Ulp2 ) );
- B2 -= common2;
- D2 -= common2;
- Ulp2 -= common2;
- // do multiplications by powers of 5 and 2
- bigB = multPow52( bigB, B5, B2 );
- OldFDBigIntForTest bigD = multPow52( new OldFDBigIntForTest( bigD0 ), D5, D2 );
- //
- // to recap:
- // bigB is the scaled-big-int version of our floating-point
- // candidate.
- // bigD is the scaled-big-int version of the exact value
- // as we understand it.
- // halfUlp is 1/2 an ulp of bigB, except for special cases
- // of exact powers of 2
- //
- // the plan is to compare bigB with bigD, and if the difference
- // is less than halfUlp, then we're satisfied. Otherwise,
- // use the ratio of difference to halfUlp to calculate a fudge
- // factor to add to the floating value, then go 'round again.
- //
- OldFDBigIntForTest diff;
- int cmpResult;
- boolean overvalue;
- if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){
- overvalue = true; // our candidate is too big.
- diff = bigB.sub( bigD );
- if ( (bigIntNBits == 1) && (bigIntExp > -expBias+1) ){
- // candidate is a normalized exact power of 2 and
- // is too big. We will be subtracting.
- // For our purposes, ulp is the ulp of the
- // next smaller range.
- Ulp2 -= 1;
- if ( Ulp2 < 0 ){
- // rats. Cannot de-scale ulp this far.
- // must scale diff in other direction.
- Ulp2 = 0;
- diff.lshiftMe( 1 );
- }
- }
- } else if ( cmpResult < 0 ){
- overvalue = false; // our candidate is too small.
- diff = bigD.sub( bigB );
- } else {
- // the candidate is exactly right!
- // this happens with surprising frequency
- break correctionLoop;
- }
- OldFDBigIntForTest halfUlp = constructPow52( B5, Ulp2 );
- if ( (cmpResult = diff.cmp( halfUlp ) ) < 0 ){
- // difference is small.
- // this is close enough
- if (mustSetRoundDir) {
- roundDir = overvalue ? -1 : 1;
- }
- break correctionLoop;
- } else if ( cmpResult == 0 ){
- // difference is exactly half an ULP
- // round to some other value maybe, then finish
- dValue += 0.5*ulp( dValue, overvalue );
- // should check for bigIntNBits == 1 here??
- if (mustSetRoundDir) {
- roundDir = overvalue ? -1 : 1;
- }
- break correctionLoop;
- } else {
- // difference is non-trivial.
- // could scale addend by ratio of difference to
- // halfUlp here, if we bothered to compute that difference.
- // Most of the time ( I hope ) it is about 1 anyway.
- dValue += ulp( dValue, overvalue );
- if ( dValue == 0.0 || dValue == Double.POSITIVE_INFINITY )
- break correctionLoop; // oops. Fell off end of range.
- continue; // try again.
- }
-
- }
- return (isNegative)? -dValue : dValue;
- }
- }
-
- /*
- * Take a FloatingDecimal, which we presumably just scanned in,
- * and find out what its value is, as a float.
- * This is distinct from doubleValue() to avoid the extremely
- * unlikely case of a double rounding error, wherein the conversion
- * to double has one rounding error, and the conversion of that double
- * to a float has another rounding error, IN THE WRONG DIRECTION,
- * ( because of the preference to a zero low-order bit ).
- */
-
- public strictfp float floatValue(){
- int kDigits = Math.min( nDigits, singleMaxDecimalDigits+1 );
- int iValue;
- float fValue;
-
- // First, check for NaN and Infinity values
- if(digits == infinity || digits == notANumber) {
- if(digits == notANumber)
- return Float.NaN;
- else
- return (isNegative?Float.NEGATIVE_INFINITY:Float.POSITIVE_INFINITY);
- }
- else {
- /*
- * convert the lead kDigits to an integer.
- */
- iValue = (int)digits[0]-(int)'0';
- for ( int i=1; i < kDigits; i++ ){
- iValue = iValue*10 + (int)digits[i]-(int)'0';
- }
- fValue = (float)iValue;
- int exp = decExponent-kDigits;
- /*
- * iValue now contains an integer with the value of
- * the first kDigits digits of the number.
- * fValue contains the (float) of the same.
- */
-
- if ( nDigits <= singleMaxDecimalDigits ){
- /*
- * possibly an easy case.
- * We know that the digits can be represented
- * exactly. And if the exponent isn't too outrageous,
- * the whole thing can be done with one operation,
- * thus one rounding error.
- * Note that all our constructors trim all leading and
- * trailing zeros, so simple values (including zero)
- * will always end up here.
- */
- if (exp == 0 || fValue == 0.0f)
- return (isNegative)? -fValue : fValue; // small floating integer
- else if ( exp >= 0 ){
- if ( exp <= singleMaxSmallTen ){
- /*
- * Can get the answer with one operation,
- * thus one roundoff.
- */
- fValue *= singleSmall10pow[exp];
- return (isNegative)? -fValue : fValue;
- }
- int slop = singleMaxDecimalDigits - kDigits;
- if ( exp <= singleMaxSmallTen+slop ){
- /*
- * We can multiply dValue by 10^(slop)
- * and it is still "small" and exact.
- * Then we can multiply by 10^(exp-slop)
- * with one rounding.
- */
- fValue *= singleSmall10pow[slop];
- fValue *= singleSmall10pow[exp-slop];
- return (isNegative)? -fValue : fValue;
- }
- /*
- * Else we have a hard case with a positive exp.
- */
- } else {
- if ( exp >= -singleMaxSmallTen ){
- /*
- * Can get the answer in one division.
- */
- fValue /= singleSmall10pow[-exp];
- return (isNegative)? -fValue : fValue;
- }
- /*
- * Else we have a hard case with a negative exp.
- */
- }
- } else if ( (decExponent >= nDigits) && (nDigits+decExponent <= maxDecimalDigits) ){
- /*
- * In double-precision, this is an exact floating integer.
- * So we can compute to double, then shorten to float
- * with one round, and get the right answer.
- *
- * First, finish accumulating digits.
- * Then convert that integer to a double, multiply
- * by the appropriate power of ten, and convert to float.
- */
- long lValue = (long)iValue;
- for ( int i=kDigits; i < nDigits; i++ ){
- lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
- }
- double dValue = (double)lValue;
- exp = decExponent-nDigits;
- dValue *= small10pow[exp];
- fValue = (float)dValue;
- return (isNegative)? -fValue : fValue;
-
- }
- /*
- * Harder cases:
- * The sum of digits plus exponent is greater than
- * what we think we can do with one error.
- *
- * Start by weeding out obviously out-of-range
- * results, then convert to double and go to
- * common hard-case code.
- */
- if ( decExponent > singleMaxDecimalExponent+1 ){
- /*
- * Lets face it. This is going to be
- * Infinity. Cut to the chase.
- */
- return (isNegative)? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
- } else if ( decExponent < singleMinDecimalExponent-1 ){
- /*
- * Lets face it. This is going to be
- * zero. Cut to the chase.
- */
- return (isNegative)? -0.0f : 0.0f;
- }
-
- /*
- * Here, we do 'way too much work, but throwing away
- * our partial results, and going and doing the whole
- * thing as double, then throwing away half the bits that computes
- * when we convert back to float.
- *
- * The alternative is to reproduce the whole multiple-precision
- * algorithm for float precision, or to try to parameterize it
- * for common usage. The former will take about 400 lines of code,
- * and the latter I tried without success. Thus the semi-hack
- * answer here.
- */
- mustSetRoundDir = !fromHex;
- double dValue = doubleValue();
- return stickyRound( dValue );
- }
- }
-
-
- /*
- * All the positive powers of 10 that can be
- * represented exactly in double/float.
- */
- private static final double small10pow[] = {
- 1.0e0,
- 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
- 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
- 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
- 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
- 1.0e21, 1.0e22
- };
-
- private static final float singleSmall10pow[] = {
- 1.0e0f,
- 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
- 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
- };
-
- private static final double big10pow[] = {
- 1e16, 1e32, 1e64, 1e128, 1e256 };
- private static final double tiny10pow[] = {
- 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
-
- private static final int maxSmallTen = small10pow.length-1;
- private static final int singleMaxSmallTen = singleSmall10pow.length-1;
-
- private static final int small5pow[] = {
- 1,
- 5,
- 5*5,
- 5*5*5,
- 5*5*5*5,
- 5*5*5*5*5,
- 5*5*5*5*5*5,
- 5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5*5*5*5
- };
-
-
- private static final long long5pow[] = {
- 1L,
- 5L,
- 5L*5,
- 5L*5*5,
- 5L*5*5*5,
- 5L*5*5*5*5,
- 5L*5*5*5*5*5,
- 5L*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- };
-
- // approximately ceil( log2( long5pow[i] ) )
- private static final int n5bits[] = {
- 0,
- 3,
- 5,
- 7,
- 10,
- 12,
- 14,
- 17,
- 19,
- 21,
- 24,
- 26,
- 28,
- 31,
- 33,
- 35,
- 38,
- 40,
- 42,
- 45,
- 47,
- 49,
- 52,
- 54,
- 56,
- 59,
- 61,
- };
-
- private static final char infinity[] = { 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y' };
- private static final char notANumber[] = { 'N', 'a', 'N' };
- private static final char zero[] = { '0', '0', '0', '0', '0', '0', '0', '0' };
-
-
- /*
- * Grammar is compatible with hexadecimal floating-point constants
- * described in section 6.4.4.2 of the C99 specification.
- */
- private static Pattern hexFloatPattern = null;
- private static synchronized Pattern getHexFloatPattern() {
- if (hexFloatPattern == null) {
- hexFloatPattern = Pattern.compile(
- //1 234 56 7 8 9
- "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
- );
- }
- return hexFloatPattern;
- }
-
- /*
- * Convert string s to a suitable floating decimal; uses the
- * double constructor and set the roundDir variable appropriately
- * in case the value is later converted to a float.
- */
- static OldFloatingDecimalForTest parseHexString(String s) {
- // Verify string is a member of the hexadecimal floating-point
- // string language.
- Matcher m = getHexFloatPattern().matcher(s);
- boolean validInput = m.matches();
-
- if (!validInput) {
- // Input does not match pattern
- throw new NumberFormatException("For input string: \"" + s + "\"");
- } else { // validInput
- /*
- * We must isolate the sign, significand, and exponent
- * fields. The sign value is straightforward. Since
- * floating-point numbers are stored with a normalized
- * representation, the significand and exponent are
- * interrelated.
- *
- * After extracting the sign, we normalized the
- * significand as a hexadecimal value, calculating an
- * exponent adjust for any shifts made during
- * normalization. If the significand is zero, the
- * exponent doesn't need to be examined since the output
- * will be zero.
- *
- * Next the exponent in the input string is extracted.
- * Afterwards, the significand is normalized as a *binary*
- * value and the input value's normalized exponent can be
- * computed. The significand bits are copied into a
- * double significand; if the string has more logical bits
- * than can fit in a double, the extra bits affect the
- * round and sticky bits which are used to round the final
- * value.
- */
-
- // Extract significand sign
- String group1 = m.group(1);
- double sign = (( group1 == null ) || group1.equals("+"))? 1.0 : -1.0;
-
-
- // Extract Significand magnitude
- /*
- * Based on the form of the significand, calculate how the
- * binary exponent needs to be adjusted to create a
- * normalized *hexadecimal* floating-point number; that
- * is, a number where there is one nonzero hex digit to
- * the left of the (hexa)decimal point. Since we are
- * adjusting a binary, not hexadecimal exponent, the
- * exponent is adjusted by a multiple of 4.
- *
- * There are a number of significand scenarios to consider;
- * letters are used in indicate nonzero digits:
- *
- * 1. 000xxxx => x.xxx normalized
- * increase exponent by (number of x's - 1)*4
- *
- * 2. 000xxx.yyyy => x.xxyyyy normalized
- * increase exponent by (number of x's - 1)*4
- *
- * 3. .000yyy => y.yy normalized
- * decrease exponent by (number of zeros + 1)*4
- *
- * 4. 000.00000yyy => y.yy normalized
- * decrease exponent by (number of zeros to right of point + 1)*4
- *
- * If the significand is exactly zero, return a properly
- * signed zero.
- */
-
- String significandString =null;
- int signifLength = 0;
- int exponentAdjust = 0;
- {
- int leftDigits = 0; // number of meaningful digits to
- // left of "decimal" point
- // (leading zeros stripped)
- int rightDigits = 0; // number of digits to right of
- // "decimal" point; leading zeros
- // must always be accounted for
- /*
- * The significand is made up of either
- *
- * 1. group 4 entirely (integer portion only)
- *
- * OR
- *
- * 2. the fractional portion from group 7 plus any
- * (optional) integer portions from group 6.
- */
- String group4;
- if( (group4 = m.group(4)) != null) { // Integer-only significand
- // Leading zeros never matter on the integer portion
- significandString = stripLeadingZeros(group4);
- leftDigits = significandString.length();
- }
- else {
- // Group 6 is the optional integer; leading zeros
- // never matter on the integer portion
- String group6 = stripLeadingZeros(m.group(6));
- leftDigits = group6.length();
-
- // fraction
- String group7 = m.group(7);
- rightDigits = group7.length();
-
- // Turn "integer.fraction" into "integer"+"fraction"
- significandString =
- ((group6 == null)?"":group6) + // is the null
- // check necessary?
- group7;
- }
-
- significandString = stripLeadingZeros(significandString);
- signifLength = significandString.length();
-
- /*
- * Adjust exponent as described above
- */
- if (leftDigits >= 1) { // Cases 1 and 2
- exponentAdjust = 4*(leftDigits - 1);
- } else { // Cases 3 and 4
- exponentAdjust = -4*( rightDigits - signifLength + 1);
- }
-
- // If the significand is zero, the exponent doesn't
- // matter; return a properly signed zero.
-
- if (signifLength == 0) { // Only zeros in input
- return new OldFloatingDecimalForTest(sign * 0.0);
- }
- }
-
- // Extract Exponent
- /*
- * Use an int to read in the exponent value; this should
- * provide more than sufficient range for non-contrived
- * inputs. If reading the exponent in as an int does
- * overflow, examine the sign of the exponent and
- * significand to determine what to do.
- */
- String group8 = m.group(8);
- boolean positiveExponent = ( group8 == null ) || group8.equals("+");
- long unsignedRawExponent;
- try {
- unsignedRawExponent = Integer.parseInt(m.group(9));
- }
- catch (NumberFormatException e) {
- // At this point, we know the exponent is
- // syntactically well-formed as a sequence of
- // digits. Therefore, if an NumberFormatException
- // is thrown, it must be due to overflowing int's
- // range. Also, at this point, we have already
- // checked for a zero significand. Thus the signs
- // of the exponent and significand determine the
- // final result:
- //
- // significand
- // + -
- // exponent + +infinity -infinity
- // - +0.0 -0.0
- return new OldFloatingDecimalForTest(sign * (positiveExponent ?
- Double.POSITIVE_INFINITY : 0.0));
- }
-
- long rawExponent =
- (positiveExponent ? 1L : -1L) * // exponent sign
- unsignedRawExponent; // exponent magnitude
-
- // Calculate partially adjusted exponent
- long exponent = rawExponent + exponentAdjust ;
-
- // Starting copying non-zero bits into proper position in
- // a long; copy explicit bit too; this will be masked
- // later for normal values.
-
- boolean round = false;
- boolean sticky = false;
- int bitsCopied=0;
- int nextShift=0;
- long significand=0L;
- // First iteration is different, since we only copy
- // from the leading significand bit; one more exponent
- // adjust will be needed...
-
- // IMPORTANT: make leadingDigit a long to avoid
- // surprising shift semantics!
- long leadingDigit = getHexDigit(significandString, 0);
-
- /*
- * Left shift the leading digit (53 - (bit position of
- * leading 1 in digit)); this sets the top bit of the
- * significand to 1. The nextShift value is adjusted
- * to take into account the number of bit positions of
- * the leadingDigit actually used. Finally, the
- * exponent is adjusted to normalize the significand
- * as a binary value, not just a hex value.
- */
- if (leadingDigit == 1) {
- significand |= leadingDigit << 52;
- nextShift = 52 - 4;
- /* exponent += 0 */ }
- else if (leadingDigit <= 3) { // [2, 3]
- significand |= leadingDigit << 51;
- nextShift = 52 - 5;
- exponent += 1;
- }
- else if (leadingDigit <= 7) { // [4, 7]
- significand |= leadingDigit << 50;
- nextShift = 52 - 6;
- exponent += 2;
- }
- else if (leadingDigit <= 15) { // [8, f]
- significand |= leadingDigit << 49;
- nextShift = 52 - 7;
- exponent += 3;
- } else {
- throw new AssertionError("Result from digit conversion too large!");
- }
- // The preceding if-else could be replaced by a single
- // code block based on the high-order bit set in
- // leadingDigit. Given leadingOnePosition,
-
- // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
- // nextShift = 52 - (3 + leadingOnePosition);
- // exponent += (leadingOnePosition-1);
-
-
- /*
- * Now the exponent variable is equal to the normalized
- * binary exponent. Code below will make representation
- * adjustments if the exponent is incremented after
- * rounding (includes overflows to infinity) or if the
- * result is subnormal.
- */
-
- // Copy digit into significand until the significand can't
- // hold another full hex digit or there are no more input
- // hex digits.
- int i = 0;
- for(i = 1;
- i < signifLength && nextShift >= 0;
- i++) {
- long currentDigit = getHexDigit(significandString, i);
- significand |= (currentDigit << nextShift);
- nextShift-=4;
- }
-
- // After the above loop, the bulk of the string is copied.
- // Now, we must copy any partial hex digits into the
- // significand AND compute the round bit and start computing
- // sticky bit.
-
- if ( i < signifLength ) { // at least one hex input digit exists
- long currentDigit = getHexDigit(significandString, i);
-
- // from nextShift, figure out how many bits need
- // to be copied, if any
- switch(nextShift) { // must be negative
- case -1:
- // three bits need to be copied in; can
- // set round bit
- significand |= ((currentDigit & 0xEL) >> 1);
- round = (currentDigit & 0x1L) != 0L;
- break;
-
- case -2:
- // two bits need to be copied in; can
- // set round and start sticky
- significand |= ((currentDigit & 0xCL) >> 2);
- round = (currentDigit &0x2L) != 0L;
- sticky = (currentDigit & 0x1L) != 0;
- break;
-
- case -3:
- // one bit needs to be copied in
- significand |= ((currentDigit & 0x8L)>>3);
- // Now set round and start sticky, if possible
- round = (currentDigit &0x4L) != 0L;
- sticky = (currentDigit & 0x3L) != 0;
- break;
-
- case -4:
- // all bits copied into significand; set
- // round and start sticky
- round = ((currentDigit & 0x8L) != 0); // is top bit set?
- // nonzeros in three low order bits?
- sticky = (currentDigit & 0x7L) != 0;
- break;
-
- default:
- throw new AssertionError("Unexpected shift distance remainder.");
- // break;
- }
-
- // Round is set; sticky might be set.
-
- // For the sticky bit, it suffices to check the
- // current digit and test for any nonzero digits in
- // the remaining unprocessed input.
- i++;
- while(i < signifLength && !sticky) {
- currentDigit = getHexDigit(significandString,i);
- sticky = sticky || (currentDigit != 0);
- i++;
- }
-
- }
- // else all of string was seen, round and sticky are
- // correct as false.
-
-
- // Check for overflow and update exponent accordingly.
-
- if (exponent > Double.MAX_EXPONENT) { // Infinite result
- // overflow to properly signed infinity
- return new OldFloatingDecimalForTest(sign * Double.POSITIVE_INFINITY);
- } else { // Finite return value
- if (exponent <= Double.MAX_EXPONENT && // (Usually) normal result
- exponent >= Double.MIN_EXPONENT) {
-
- // The result returned in this block cannot be a
- // zero or subnormal; however after the
- // significand is adjusted from rounding, we could
- // still overflow in infinity.
-
- // AND exponent bits into significand; if the
- // significand is incremented and overflows from
- // rounding, this combination will update the
- // exponent correctly, even in the case of
- // Double.MAX_VALUE overflowing to infinity.
-
- significand = (( (exponent +
- (long)DoubleConsts.EXP_BIAS) <<
- (DoubleConsts.SIGNIFICAND_WIDTH-1))
- & DoubleConsts.EXP_BIT_MASK) |
- (DoubleConsts.SIGNIF_BIT_MASK & significand);
-
- } else { // Subnormal or zero
- // (exponent < Double.MIN_EXPONENT)
-
- if (exponent < (DoubleConsts.MIN_SUB_EXPONENT -1 )) {
- // No way to round back to nonzero value
- // regardless of significand if the exponent is
- // less than -1075.
- return new OldFloatingDecimalForTest(sign * 0.0);
- } else { // -1075 <= exponent <= MIN_EXPONENT -1 = -1023
- /*
- * Find bit position to round to; recompute
- * round and sticky bits, and shift
- * significand right appropriately.
- */
-
- sticky = sticky || round;
- round = false;
-
- // Number of bits of significand to preserve is
- // exponent - abs_min_exp +1
- // check:
- // -1075 +1074 + 1 = 0
- // -1023 +1074 + 1 = 52
-
- int bitsDiscarded = 53 -
- ((int)exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
- assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
-
- // What to do here:
- // First, isolate the new round bit
- round = (significand & (1L << (bitsDiscarded -1))) != 0L;
- if (bitsDiscarded > 1) {
- // create mask to update sticky bits; low
- // order bitsDiscarded bits should be 1
- long mask = ~((~0L) << (bitsDiscarded -1));
- sticky = sticky || ((significand & mask) != 0L ) ;
- }
-
- // Now, discard the bits
- significand = significand >> bitsDiscarded;
-
- significand = (( ((long)(Double.MIN_EXPONENT -1) + // subnorm exp.
- (long)DoubleConsts.EXP_BIAS) <<
- (DoubleConsts.SIGNIFICAND_WIDTH-1))
- & DoubleConsts.EXP_BIT_MASK) |
- (DoubleConsts.SIGNIF_BIT_MASK & significand);
- }
- }
-
- // The significand variable now contains the currently
- // appropriate exponent bits too.
-
- /*
- * Determine if significand should be incremented;
- * making this determination depends on the least
- * significant bit and the round and sticky bits.
- *
- * Round to nearest even rounding table, adapted from
- * table 4.7 in "Computer Arithmetic" by IsraelKoren.
- * The digit to the left of the "decimal" point is the
- * least significant bit, the digits to the right of
- * the point are the round and sticky bits
- *
- * Number Round(x)
- * x0.00 x0.
- * x0.01 x0.
- * x0.10 x0.
- * x0.11 x1. = x0. +1
- * x1.00 x1.
- * x1.01 x1.
- * x1.10 x1. + 1
- * x1.11 x1. + 1
- */
- boolean incremented = false;
- boolean leastZero = ((significand & 1L) == 0L);
- if( ( leastZero && round && sticky ) ||
- ((!leastZero) && round )) {
- incremented = true;
- significand++;
- }
-
- OldFloatingDecimalForTest fd = new OldFloatingDecimalForTest(Math.copySign(
- Double.longBitsToDouble(significand),
- sign));
-
- /*
- * Set roundingDir variable field of fd properly so
- * that the input string can be properly rounded to a
- * float value. There are two cases to consider:
- *
- * 1. rounding to double discards sticky bit
- * information that would change the result of a float
- * rounding (near halfway case between two floats)
- *
- * 2. rounding to double rounds up when rounding up
- * would not occur when rounding to float.
- *
- * For former case only needs to be considered when
- * the bits rounded away when casting to float are all
- * zero; otherwise, float round bit is properly set
- * and sticky will already be true.
- *
- * The lower exponent bound for the code below is the
- * minimum (normalized) subnormal exponent - 1 since a
- * value with that exponent can round up to the
- * minimum subnormal value and the sticky bit
- * information must be preserved (i.e. case 1).
- */
- if ((exponent >= FloatConsts.MIN_SUB_EXPONENT-1) &&
- (exponent <= Float.MAX_EXPONENT ) ){
- // Outside above exponent range, the float value
- // will be zero or infinity.
-
- /*
- * If the low-order 28 bits of a rounded double
- * significand are 0, the double could be a
- * half-way case for a rounding to float. If the
- * double value is a half-way case, the double
- * significand may have to be modified to round
- * the the right float value (see the stickyRound
- * method). If the rounding to double has lost
- * what would be float sticky bit information, the
- * double significand must be incremented. If the
- * double value's significand was itself
- * incremented, the float value may end up too
- * large so the increment should be undone.
- */
- if ((significand & 0xfffffffL) == 0x0L) {
- // For negative values, the sign of the
- // roundDir is the same as for positive values
- // since adding 1 increasing the significand's
- // magnitude and subtracting 1 decreases the
- // significand's magnitude. If neither round
- // nor sticky is true, the double value is
- // exact and no adjustment is required for a
- // proper float rounding.
- if( round || sticky) {
- if (leastZero) { // prerounding lsb is 0
- // If round and sticky were both true,
- // and the least significant
- // significand bit were 0, the rounded
- // significand would not have its
- // low-order bits be zero. Therefore,
- // we only need to adjust the
- // significand if round XOR sticky is
- // true.
- if (round ^ sticky) {
- fd.roundDir = 1;
- }
- }
- else { // prerounding lsb is 1
- // If the prerounding lsb is 1 and the
- // resulting significand has its
- // low-order bits zero, the significand
- // was incremented. Here, we undo the
- // increment, which will ensure the
- // right guard and sticky bits for the
- // float rounding.
- if (round)
- fd.roundDir = -1;
- }
- }
- }
- }
-
- fd.fromHex = true;
- return fd;
- }
- }
- }
-
- /**
- * Return <code>s</code> with any leading zeros removed.
- */
- static String stripLeadingZeros(String s) {
- return s.replaceFirst("^0+", "");
- }
-
- /**
- * Extract a hexadecimal digit from position <code>position</code>
- * of string <code>s</code>.
- */
- static int getHexDigit(String s, int position) {
- int value = Character.digit(s.charAt(position), 16);
- if (value <= -1 || value >= 16) {
- throw new AssertionError("Unexpected failure of digit conversion of " +
- s.charAt(position));
- }
- return value;
- }
-
-
-}
--- a/jdk/test/sun/misc/FloatingDecimal/TestFDBigInteger.java Tue Dec 22 11:07:17 2015 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,435 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.math.BigInteger;
-import java.util.Random;
-import sun.misc.FDBigInteger;
-
-/**
- * @test
- * @bug 7032154
- * @summary unit testys of sun.misc.FDBigInteger
- * @modules java.base/sun.misc
- * @author Dmitry Nadezhin
- */
-public class TestFDBigInteger {
-
- private static final int MAX_P5 = 413;
- private static final int MAX_P2 = 65;
- private static final long LONG_SIGN_MASK = (1L << 63);
- private static final BigInteger FIVE = BigInteger.valueOf(5);
- private static final FDBigInteger MUTABLE_ZERO = FDBigInteger.valueOfPow52(0, 0).leftInplaceSub(FDBigInteger.valueOfPow52(0, 0));
- private static final FDBigInteger IMMUTABLE_ZERO = FDBigInteger.valueOfPow52(0, 0).leftInplaceSub(FDBigInteger.valueOfPow52(0, 0));
- private static final FDBigInteger IMMUTABLE_MILLION = genMillion1();
- private static final FDBigInteger IMMUTABLE_BILLION = genBillion1();
- private static final FDBigInteger IMMUTABLE_TEN18 = genTen18();
-
- static {
- IMMUTABLE_ZERO.makeImmutable();
- IMMUTABLE_MILLION.makeImmutable();
- IMMUTABLE_BILLION.makeImmutable();
- IMMUTABLE_TEN18.makeImmutable();
- }
-
- private static FDBigInteger mutable(String hex, int offset) {
- char[] chars = new BigInteger(hex, 16).toString().toCharArray();
- return new FDBigInteger(0, chars, 0, chars.length).multByPow52(0, offset * 32);
- }
-
- private static FDBigInteger immutable(String hex, int offset) {
- FDBigInteger fd = mutable(hex, offset);
- fd.makeImmutable();
- return fd;
- }
-
- private static BigInteger biPow52(int p5, int p2) {
- return FIVE.pow(p5).shiftLeft(p2);
- }
-
- // data.length == 1, nWords == 1, offset == 0
- private static FDBigInteger genMillion1() {
- return FDBigInteger.valueOfPow52(6, 0).leftShift(6);
- }
-
- // data.length == 2, nWords == 1, offset == 0
- private static FDBigInteger genMillion2() {
- return FDBigInteger.valueOfMulPow52(1000000L, 0, 0);
- }
-
- // data.length == 1, nWords == 1, offset == 0
- private static FDBigInteger genBillion1() {
- return FDBigInteger.valueOfPow52(9, 0).leftShift(9);
- }
-
- // data.length == 2, nWords == 2, offset == 0
- private static FDBigInteger genTen18() {
- return FDBigInteger.valueOfPow52(18, 0).leftShift(18);
- }
-
- private static void check(BigInteger expected, FDBigInteger actual, String message) throws Exception {
- if (!expected.equals(actual.toBigInteger())) {
- throw new Exception(message + " result " + actual.toHexString() + " expected " + expected.toString(16));
- }
- }
-
- private static void testValueOfPow52(int p5, int p2) throws Exception {
- check(biPow52(p5, p2), FDBigInteger.valueOfPow52(p5, p2),
- "valueOfPow52(" + p5 + "," + p2 + ")");
- }
-
- private static void testValueOfPow52() throws Exception {
- for (int p5 = 0; p5 <= MAX_P5; p5++) {
- for (int p2 = 0; p2 <= MAX_P2; p2++) {
- testValueOfPow52(p5, p2);
- }
- }
- }
-
- private static void testValueOfMulPow52(long value, int p5, int p2) throws Exception {
- BigInteger bi = BigInteger.valueOf(value & ~LONG_SIGN_MASK);
- if (value < 0) {
- bi = bi.setBit(63);
- }
- check(biPow52(p5, p2).multiply(bi), FDBigInteger.valueOfMulPow52(value, p5, p2),
- "valueOfMulPow52(" + Long.toHexString(value) + "." + p5 + "," + p2 + ")");
- }
-
- private static void testValueOfMulPow52(long value, int p5) throws Exception {
- testValueOfMulPow52(value, p5, 0);
- testValueOfMulPow52(value, p5, 1);
- testValueOfMulPow52(value, p5, 30);
- testValueOfMulPow52(value, p5, 31);
- testValueOfMulPow52(value, p5, 33);
- testValueOfMulPow52(value, p5, 63);
- }
-
- private static void testValueOfMulPow52() throws Exception {
- for (int p5 = 0; p5 <= MAX_P5; p5++) {
- testValueOfMulPow52(0xFFFFFFFFL, p5);
- testValueOfMulPow52(0x123456789AL, p5);
- testValueOfMulPow52(0x7FFFFFFFFFFFFFFFL, p5);
- testValueOfMulPow52(0xFFFFFFFFFFF54321L, p5);
- }
- }
-
- private static void testLeftShift(FDBigInteger t, int shift, boolean isImmutable) throws Exception {
- BigInteger bt = t.toBigInteger();
- FDBigInteger r = t.leftShift(shift);
- if ((bt.signum() == 0 || shift == 0 || !isImmutable) && r != t) {
- throw new Exception("leftShift doesn't reuse its argument");
- }
- if (isImmutable) {
- check(bt, t, "leftShift corrupts its argument");
- }
- check(bt.shiftLeft(shift), r, "leftShift returns wrong result");
- }
-
- private static void testLeftShift() throws Exception {
- testLeftShift(IMMUTABLE_ZERO, 0, true);
- testLeftShift(IMMUTABLE_ZERO, 10, true);
- testLeftShift(MUTABLE_ZERO, 0, false);
- testLeftShift(MUTABLE_ZERO, 10, false);
-
- testLeftShift(IMMUTABLE_MILLION, 0, true);
- testLeftShift(IMMUTABLE_MILLION, 1, true);
- testLeftShift(IMMUTABLE_MILLION, 12, true);
- testLeftShift(IMMUTABLE_MILLION, 13, true);
- testLeftShift(IMMUTABLE_MILLION, 32, true);
- testLeftShift(IMMUTABLE_MILLION, 33, true);
- testLeftShift(IMMUTABLE_MILLION, 44, true);
- testLeftShift(IMMUTABLE_MILLION, 45, true);
-
- testLeftShift(genMillion1(), 0, false);
- testLeftShift(genMillion1(), 1, false);
- testLeftShift(genMillion1(), 12, false);
- testLeftShift(genMillion1(), 13, false);
- testLeftShift(genMillion1(), 25, false);
- testLeftShift(genMillion1(), 26, false);
- testLeftShift(genMillion1(), 32, false);
- testLeftShift(genMillion1(), 33, false);
- testLeftShift(genMillion1(), 44, false);
- testLeftShift(genMillion1(), 45, false);
-
- testLeftShift(genMillion2(), 0, false);
- testLeftShift(genMillion2(), 1, false);
- testLeftShift(genMillion2(), 12, false);
- testLeftShift(genMillion2(), 13, false);
- testLeftShift(genMillion2(), 25, false);
- testLeftShift(genMillion2(), 26, false);
- testLeftShift(genMillion2(), 32, false);
- testLeftShift(genMillion2(), 33, false);
- testLeftShift(genMillion2(), 44, false);
- testLeftShift(genMillion2(), 45, false);
- }
-
- private static void testQuoRemIteration(FDBigInteger t, FDBigInteger s) throws Exception {
- BigInteger bt = t.toBigInteger();
- BigInteger bs = s.toBigInteger();
- int q = t.quoRemIteration(s);
- BigInteger[] qr = bt.divideAndRemainder(bs);
- if (!BigInteger.valueOf(q).equals(qr[0])) {
- throw new Exception("quoRemIteration returns incorrect quo");
- }
- check(qr[1].multiply(BigInteger.TEN), t, "quoRemIteration returns incorrect rem");
- }
-
- private static void testQuoRemIteration() throws Exception {
- // IMMUTABLE_TEN18 == 0de0b6b3a7640000
- // q = 0
- testQuoRemIteration(mutable("00000001", 0), IMMUTABLE_TEN18);
- testQuoRemIteration(mutable("00000001", 1), IMMUTABLE_TEN18);
- testQuoRemIteration(mutable("0de0b6b2", 1), IMMUTABLE_TEN18);
- // q = 1 -> q = 0
- testQuoRemIteration(mutable("0de0b6b3", 1), IMMUTABLE_TEN18);
- testQuoRemIteration(mutable("0de0b6b3a763FFFF", 0), IMMUTABLE_TEN18);
- // q = 1
- testQuoRemIteration(mutable("0de0b6b3a7640000", 0), IMMUTABLE_TEN18);
- testQuoRemIteration(mutable("0de0b6b3FFFFFFFF", 0), IMMUTABLE_TEN18);
- testQuoRemIteration(mutable("8ac72304", 1), IMMUTABLE_TEN18);
- testQuoRemIteration(mutable("0de0b6b400000000", 0), IMMUTABLE_TEN18);
- testQuoRemIteration(mutable("8ac72305", 1), IMMUTABLE_TEN18);
- // q = 18
- testQuoRemIteration(mutable("FFFFFFFF", 1), IMMUTABLE_TEN18);
- }
-
- private static void testCmp(FDBigInteger t, FDBigInteger o) throws Exception {
- BigInteger bt = t.toBigInteger();
- BigInteger bo = o.toBigInteger();
- int cmp = t.cmp(o);
- int bcmp = bt.compareTo(bo);
- if (bcmp != cmp) {
- throw new Exception("cmp returns " + cmp + " expected " + bcmp);
- }
- check(bt, t, "cmp corrupts this");
- check(bo, o, "cmp corrupts other");
- if (o.cmp(t) != -cmp) {
- throw new Exception("asymmetrical cmp");
- }
- check(bt, t, "cmp corrupts this");
- check(bo, o, "cmp corrupts other");
- }
-
- private static void testCmp() throws Exception {
- testCmp(mutable("FFFFFFFF", 0), mutable("100000000", 0));
- testCmp(mutable("FFFFFFFF", 0), mutable("1", 1));
- testCmp(mutable("5", 0), mutable("6", 0));
- testCmp(mutable("5", 0), mutable("5", 0));
- testCmp(mutable("5000000001", 0), mutable("500000001", 0));
- testCmp(mutable("5000000001", 0), mutable("6", 1));
- testCmp(mutable("5000000001", 0), mutable("5", 1));
- testCmp(mutable("5000000000", 0), mutable("5", 1));
- }
-
- private static void testCmpPow52(FDBigInteger t, int p5, int p2) throws Exception {
- FDBigInteger o = FDBigInteger.valueOfPow52(p5, p2);
- BigInteger bt = t.toBigInteger();
- BigInteger bo = biPow52(p5, p2);
- int cmp = t.cmp(o);
- int bcmp = bt.compareTo(bo);
- if (bcmp != cmp) {
- throw new Exception("cmpPow52 returns " + cmp + " expected " + bcmp);
- }
- check(bt, t, "cmpPow52 corrupts this");
- check(bo, o, "cmpPow5 corrupts other");
- }
-
- private static void testCmpPow52() throws Exception {
- testCmpPow52(mutable("00000002", 1), 0, 31);
- testCmpPow52(mutable("00000002", 1), 0, 32);
- testCmpPow52(mutable("00000002", 1), 0, 33);
- testCmpPow52(mutable("00000002", 1), 0, 34);
- testCmpPow52(mutable("00000002", 1), 0, 64);
- testCmpPow52(mutable("00000003", 1), 0, 32);
- testCmpPow52(mutable("00000003", 1), 0, 33);
- testCmpPow52(mutable("00000003", 1), 0, 34);
- }
-
- private static void testAddAndCmp(FDBigInteger t, FDBigInteger x, FDBigInteger y) throws Exception {
- BigInteger bt = t.toBigInteger();
- BigInteger bx = x.toBigInteger();
- BigInteger by = y.toBigInteger();
- int cmp = t.addAndCmp(x, y);
- int bcmp = bt.compareTo(bx.add(by));
- if (bcmp != cmp) {
- throw new Exception("addAndCmp returns " + cmp + " expected " + bcmp);
- }
- check(bt, t, "addAndCmp corrupts this");
- check(bx, x, "addAndCmp corrupts x");
- check(by, y, "addAndCmp corrupts y");
- }
-
- private static void testAddAndCmp() throws Exception {
- testAddAndCmp(MUTABLE_ZERO, MUTABLE_ZERO, MUTABLE_ZERO);
- testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, MUTABLE_ZERO);
- testAddAndCmp(mutable("00000001", 0), mutable("00000001", 0), MUTABLE_ZERO);
- testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, mutable("00000001", 0));
- testAddAndCmp(mutable("00000001", 0), mutable("00000002", 0), MUTABLE_ZERO);
- testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, mutable("00000002", 0));
- testAddAndCmp(mutable("00000001", 2), mutable("FFFFFFFF", 0), mutable("FFFFFFFF", 0));
- testAddAndCmp(mutable("00000001", 0), mutable("00000001", 1), mutable("00000001", 0));
-
- testAddAndCmp(mutable("00000001", 2), mutable("0F0F0F0F80000000", 1), mutable("F0F0F0F080000000", 1));
- testAddAndCmp(mutable("00000001", 2), mutable("0F0F0F0E80000000", 1), mutable("F0F0F0F080000000", 1));
-
- testAddAndCmp(mutable("00000002", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
- testAddAndCmp(mutable("00000003", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
- testAddAndCmp(mutable("00000004", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
- testAddAndCmp(mutable("00000005", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
-
- testAddAndCmp(mutable("00000001", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
- testAddAndCmp(mutable("00000001", 2), mutable("8000000000000000", 0), mutable("8000000000000001", 0));
- testAddAndCmp(mutable("00000002", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
- testAddAndCmp(mutable("00000003", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
- }
-
- private static void testMultBy10(FDBigInteger t, boolean isImmutable) throws Exception {
- BigInteger bt = t.toBigInteger();
- FDBigInteger r = t.multBy10();
- if ((bt.signum() == 0 || !isImmutable) && r != t) {
- throw new Exception("multBy10 of doesn't reuse its argument");
- }
- if (isImmutable) {
- check(bt, t, "multBy10 corrupts its argument");
- }
- check(bt.multiply(BigInteger.TEN), r, "multBy10 returns wrong result");
- }
-
- private static void testMultBy10() throws Exception {
- for (int p5 = 0; p5 <= MAX_P5; p5++) {
- for (int p2 = 0; p2 <= MAX_P2; p2++) {
- // This strange way of creating a value ensures that it is mutable.
- FDBigInteger value = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
- testMultBy10(value, false);
- value.makeImmutable();
- testMultBy10(value, true);
- }
- }
- }
-
- private static void testMultByPow52(FDBigInteger t, int p5, int p2) throws Exception {
- BigInteger bt = t.toBigInteger();
- FDBigInteger r = t.multByPow52(p5, p2);
- if (bt.signum() == 0 && r != t) {
- throw new Exception("multByPow52 of doesn't reuse its argument");
- }
- check(bt.multiply(biPow52(p5, p2)), r, "multByPow52 returns wrong result");
- }
-
- private static void testMultByPow52() throws Exception {
- for (int p5 = 0; p5 <= MAX_P5; p5++) {
- for (int p2 = 0; p2 <= MAX_P2; p2++) {
- // This strange way of creating a value ensures that it is mutable.
- FDBigInteger value = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
- testMultByPow52(value, p5, p2);
- }
- }
- }
-
- private static void testLeftInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable) throws Exception {
- BigInteger biLeft = left.toBigInteger();
- BigInteger biRight = right.toBigInteger();
- FDBigInteger diff = left.leftInplaceSub(right);
- if (!isImmutable && diff != left) {
- throw new Exception("leftInplaceSub of doesn't reuse its argument");
- }
- if (isImmutable) {
- check(biLeft, left, "leftInplaceSub corrupts its left immutable argument");
- }
- check(biRight, right, "leftInplaceSub corrupts its right argument");
- check(biLeft.subtract(biRight), diff, "leftInplaceSub returns wrong result");
- }
-
- private static void testLeftInplaceSub() throws Exception {
- for (int p5 = 0; p5 <= MAX_P5; p5++) {
- for (int p2 = 0; p2 <= MAX_P2; p2++) {
-// for (int p5r = 0; p5r <= p5; p5r += 10) {
-// for (int p2r = 0; p2r <= p2; p2r += 10) {
- for (int p5r = 0; p5r <= p5; p5r++) {
- for (int p2r = 0; p2r <= p2; p2r++) {
- // This strange way of creating a value ensures that it is mutable.
- FDBigInteger left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
- FDBigInteger right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
- testLeftInplaceSub(left, right, false);
- left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
- left.makeImmutable();
- testLeftInplaceSub(left, right, true);
- }
- }
- }
- }
- }
-
- private static void testRightInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable) throws Exception {
- BigInteger biLeft = left.toBigInteger();
- BigInteger biRight = right.toBigInteger();
- FDBigInteger diff = left.rightInplaceSub(right);
- if (!isImmutable && diff != right) {
- throw new Exception("rightInplaceSub of doesn't reuse its argument");
- }
- check(biLeft, left, "leftInplaceSub corrupts its left argument");
- if (isImmutable) {
- check(biRight, right, "leftInplaceSub corrupts its right immutable argument");
- }
- try {
- check(biLeft.subtract(biRight), diff, "rightInplaceSub returns wrong result");
- } catch (Exception e) {
- System.out.println(biLeft+" - "+biRight+" = "+biLeft.subtract(biRight));
- throw e;
- }
- }
-
- private static void testRightInplaceSub() throws Exception {
- for (int p5 = 0; p5 <= MAX_P5; p5++) {
- for (int p2 = 0; p2 <= MAX_P2; p2++) {
-// for (int p5r = 0; p5r <= p5; p5r += 10) {
-// for (int p2r = 0; p2r <= p2; p2r += 10) {
- for (int p5r = 0; p5r <= p5; p5r++) {
- for (int p2r = 0; p2r <= p2; p2r++) {
- // This strange way of creating a value ensures that it is mutable.
- FDBigInteger left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
- FDBigInteger right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
- testRightInplaceSub(left, right, false);
- right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
- right.makeImmutable();
- testRightInplaceSub(left, right, true);
- }
- }
- }
- }
- }
-
- public static void main(String[] args) throws Exception {
- testValueOfPow52();
- testValueOfMulPow52();
- testLeftShift();
- testQuoRemIteration();
- testCmp();
- testCmpPow52();
- testAddAndCmp();
- // Uncomment the following for more comprehensize but slow testing.
- // testLeftInplaceSub();
- // testMultBy10();
- // testMultByPow52();
- // testRightInplaceSub();
- }
-}
--- a/jdk/test/sun/misc/FloatingDecimal/TestFloatingDecimal.java Tue Dec 22 11:07:17 2015 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,329 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.util.Random;
-import sun.misc.FloatingDecimal;
-
-/*
-OldFloatingDecimalForTest
-
-public class OldFloatingDecimalForTest {
- public boolean digitsRoundedUp();
- public OldFloatingDecimalForTest(double);
- public OldFloatingDecimalForTest(float);
- public boolean decimalDigitsExact();
- public java.lang.String toString();
- public java.lang.String toJavaFormatString();
- public void appendTo(java.lang.Appendable);
- public static OldFloatingDecimalForTest readJavaFormatString(java.lang.String) throws java.lang.NumberFormatException;
- public strictfp double doubleValue();
- public strictfp float floatValue();
-}
-
-sun.misc.FloatingDecimal
-
-public class sun.misc.FloatingDecimal {
- public sun.misc.FloatingDecimal();
- public static java.lang.String toJavaFormatString(double);
- public static java.lang.String toJavaFormatString(float);
- public static void appendTo(double, java.lang.Appendable);
- public static void appendTo(float, java.lang.Appendable);
- public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException;
- public static float parseFloat(java.lang.String) throws java.lang.NumberFormatException;
- public static sun.misc.FloatingDecimal$AbstractD2ABuffer getD2ABuffer(double);
-}
-*/
-
-/**
- * @test
- * @bug 7032154
- * @summary unit tests of sun.misc.FloatingDecimal
- * @modules java.base/sun.misc
- * @library ../../../java/lang/Math
- * @build DoubleConsts FloatConsts
- * @run main TestFloatingDecimal
- * @author Brian Burkhalter
- * @key randomness
- */
-public class TestFloatingDecimal {
- private static enum ResultType {
- RESULT_EXCEPTION,
- RESULT_PRINT
- }
-
- private static final ResultType RESULT_TYPE = ResultType.RESULT_PRINT;
- private static final int NUM_RANDOM_TESTS = 100000;
-
- private static final Random RANDOM = new Random();
-
- private static void result(String message) {
- switch (RESULT_TYPE) {
- case RESULT_EXCEPTION:
- throw new RuntimeException(message);
- case RESULT_PRINT:
- System.err.println(message);
- break;
- default:
- assert false;
- }
- }
-
- private static int check(String test, Object expected, Object actual) {
- int failures = 0;
- if(!actual.equals(expected)) {
- failures++;
- result("Test "+test+" expected "+expected+" but obtained "+actual);
- }
- return failures;
- }
-
- private static int testAppendToDouble() {
- System.out.println(" testAppendToDouble");
- int failures = 0;
-
- for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
- double[] d = new double[] {
- RANDOM.nextLong(),
- RANDOM.nextGaussian(),
- RANDOM.nextDouble()*Double.MAX_VALUE
- };
- for(int j = 0; j < d.length; j++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]);
- StringBuilder sb = new StringBuilder();
- ofd.appendTo(sb);
- String oldString = sb.toString();
- sb = new StringBuilder();
- FloatingDecimal.appendTo(d[j], sb);
- String newString = sb.toString();
- failures += check("testAppendToDouble", oldString, newString);
- }
- }
-
- return failures;
- }
-
- private static int testAppendToFloat() {
- System.out.println(" testAppendToFloat");
- int failures = 0;
-
- for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
- float[] f = new float[] {
- RANDOM.nextLong(),
- (float)RANDOM.nextGaussian(),
- RANDOM.nextFloat()*Float.MAX_VALUE
- };
- for(int j = 0; j < f.length; j++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]);
- StringBuilder sb = new StringBuilder();
- ofd.appendTo(sb);
- String oldString = sb.toString();
- sb = new StringBuilder();
- FloatingDecimal.appendTo(f[j], sb);
- String newString = sb.toString();
- failures += check("testAppendToFloat", oldString, newString);
- }
- }
-
- return failures;
- }
-
- private static int testAppendTo() {
- System.out.println("testAppendTo");
- int failures = 0;
-
- failures += testAppendToDouble();
- failures += testAppendToFloat();
-
- return failures;
- }
-
- private static int testParseDouble() {
- System.out.println(" testParseDouble");
- int failures = 0;
-
- for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
- double[] d = new double[] {
- RANDOM.nextLong(),
- RANDOM.nextGaussian(),
- RANDOM.nextDouble()*Double.MAX_VALUE
- };
- for(int j = 0; j < d.length; j++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]);
- String javaFormatString = ofd.toJavaFormatString();
- ofd = OldFloatingDecimalForTest.readJavaFormatString(javaFormatString);
- double oldDouble = ofd.doubleValue();
- double newDouble = FloatingDecimal.parseDouble(javaFormatString);
- failures += check("testParseDouble", oldDouble, newDouble);
- }
- }
-
- return failures;
- }
-
- private static int testParseFloat() {
- System.out.println(" testParseFloat");
- int failures = 0;
-
- for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
- float[] f = new float[] {
- RANDOM.nextInt(),
- (float)RANDOM.nextGaussian(),
- RANDOM.nextFloat()*Float.MAX_VALUE
- };
- for(int j = 0; j < f.length; j++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]);
- String javaFormatString = ofd.toJavaFormatString();
- ofd = OldFloatingDecimalForTest.readJavaFormatString(javaFormatString);
- float oldFloat = ofd.floatValue();
- float newFloat = FloatingDecimal.parseFloat(javaFormatString);
- failures += check("testParseFloat", oldFloat, newFloat);
- }
- }
-
- return failures;
- }
-
- private static int testParse() {
- System.out.println("testParse");
- int failures = 0;
-
- failures += testParseDouble();
- failures += testParseFloat();
-
- return failures;
- }
-
- private static int testToJavaFormatStringDoubleFixed() {
- System.out.println(" testToJavaFormatStringDoubleFixed");
- int failures = 0;
-
- double[] d = new double [] {
- -5.9522650387500933e18, // dtoa() fast path
- 0.872989018674569, // dtoa() fast iterative - long
- 1.1317400099603851e308 // dtoa() slow iterative
- };
-
- for(int i = 0; i < d.length; i++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[i]);
- failures += check("testToJavaFormatStringDoubleFixed", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(d[i]));
- }
-
- return failures;
- }
-
- private static int testToJavaFormatStringDoubleRandom() {
- System.out.println(" testToJavaFormatStringDoubleRandom");
- int failures = 0;
-
- for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
- double[] d = new double[] {
- RANDOM.nextLong(),
- RANDOM.nextGaussian(),
- RANDOM.nextDouble()*Double.MAX_VALUE
- };
- for(int j = 0; j < d.length; j++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]);
- failures += check("testToJavaFormatStringDoubleRandom", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(d[j]));
- }
- }
-
- return failures;
- }
-
- private static int testToJavaFormatStringDouble() {
- System.out.println(" testToJavaFormatStringDouble");
- int failures = 0;
- failures += testToJavaFormatStringDoubleFixed();
- failures += testToJavaFormatStringDoubleRandom();
- return failures;
- }
-
- private static int testToJavaFormatStringFloatFixed() {
- System.out.println(" testToJavaFormatStringFloatFixed");
- int failures = 0;
-
- float[] f = new float[] {
- -9.8784166e8f, // dtoa() fast path
- 0.70443946f, // dtoa() fast iterative - int
- 1.8254228e37f // dtoa() slow iterative
- };
-
- for(int i = 0; i < f.length; i++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[i]);
- failures += check("testToJavaFormatStringFloatFixed", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(f[i]));
- }
-
- return failures;
- }
-
- private static int testToJavaFormatStringFloatRandom() {
- System.out.println(" testToJavaFormatStringFloatRandom");
- int failures = 0;
-
- for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
- float[] f = new float[] {
- RANDOM.nextInt(),
- (float)RANDOM.nextGaussian(),
- RANDOM.nextFloat()*Float.MAX_VALUE
- };
- for(int j = 0; j < f.length; j++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]);
- failures += check("testToJavaFormatStringFloatRandom", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(f[j]));
- }
- }
-
- return failures;
- }
-
- private static int testToJavaFormatStringFloat() {
- System.out.println(" testToJavaFormatStringFloat");
- int failures = 0;
-
- failures += testToJavaFormatStringFloatFixed();
- failures += testToJavaFormatStringFloatRandom();
-
- return failures;
- }
-
- private static int testToJavaFormatString() {
- System.out.println("testToJavaFormatString");
- int failures = 0;
-
- failures += testToJavaFormatStringDouble();
- failures += testToJavaFormatStringFloat();
-
- return failures;
- }
-
- public static void main(String[] args) {
- int failures = 0;
-
- failures += testAppendTo();
- failures += testParse();
- failures += testToJavaFormatString();
-
- if (failures != 0) {
- throw new RuntimeException("" + failures + " failures while testing FloatingDecimal");
- }
- }
-}