7050528: Improve performance of java.text.DecimalFormat.format() call stack
authorolagneau
Tue, 02 Oct 2012 10:11:57 +0100
changeset 14015 f771d5fb3b27
parent 14014 da3648e13e67
child 14016 56be5085fc31
7050528: Improve performance of java.text.DecimalFormat.format() call stack Reviewed-by: darcy
jdk/src/share/classes/java/text/DecimalFormat.java
jdk/src/share/classes/java/text/NumberFormat.java
jdk/test/java/text/Format/DecimalFormat/FormatMicroBenchmark.java
jdk/test/java/text/Format/DecimalFormat/GoldenDoubleValues.java
jdk/test/java/text/Format/DecimalFormat/GoldenFormattedValues.java
jdk/test/java/text/Format/DecimalFormat/RoundingAndPropertyTest.java
--- a/jdk/src/share/classes/java/text/DecimalFormat.java	Mon Oct 01 15:36:57 2012 +0100
+++ b/jdk/src/share/classes/java/text/DecimalFormat.java	Tue Oct 02 10:11:57 2012 +0100
@@ -529,9 +529,25 @@
     @Override
     public StringBuffer format(double number, StringBuffer result,
                                FieldPosition fieldPosition) {
-        fieldPosition.setBeginIndex(0);
-        fieldPosition.setEndIndex(0);
-
+        // If fieldPosition is a DontCareFieldPosition instance we can
+        // try to go to fast-path code.
+        boolean tryFastPath = false;
+        if (fieldPosition == DontCareFieldPosition.INSTANCE)
+            tryFastPath = true;
+        else {
+            fieldPosition.setBeginIndex(0);
+            fieldPosition.setEndIndex(0);
+        }
+
+        if (tryFastPath) {
+            String tempResult = fastFormat(number);
+            if (tempResult != null) {
+                result.append(tempResult);
+                return result;
+            }
+        }
+
+        // if fast-path could not work, we fallback to standard code.
         return format(number, result, fieldPosition.getFieldDelegate());
     }
 
@@ -869,6 +885,720 @@
         return delegate.getIterator(sb.toString());
     }
 
+    // ==== Begin fast-path formating logic for double =========================
+
+    /* Fast-path formatting will be used for format(double ...) methods iff a
+     * number of conditions are met (see checkAndSetFastPathStatus()):
+     * - Only if instance properties meet the right predefined conditions.
+     * - The abs value of the double to format is <= Integer.MAX_VALUE.
+     *
+     * The basic approach is to split the binary to decimal conversion of a
+     * double value into two phases:
+     * * The conversion of the integer portion of the double.
+     * * The conversion of the fractional portion of the double
+     *   (limited to two or three digits).
+     *
+     * The isolation and conversion of the integer portion of the double is
+     * straightforward. The conversion of the fraction is more subtle and relies
+     * on some rounding properties of double to the decimal precisions in
+     * question.  Using the terminology of BigDecimal, this fast-path algorithm
+     * is applied when a double value has a magnitude less than Integer.MAX_VALUE
+     * and rounding is to nearest even and the destination format has two or
+     * three digits of *scale* (digits after the decimal point).
+     *
+     * Under a rounding to nearest even policy, the returned result is a digit
+     * string of a number in the (in this case decimal) destination format
+     * closest to the exact numerical value of the (in this case binary) input
+     * value.  If two destination format numbers are equally distant, the one
+     * with the last digit even is returned.  To compute such a correctly rounded
+     * value, some information about digits beyond the smallest returned digit
+     * position needs to be consulted.
+     *
+     * In general, a guard digit, a round digit, and a sticky *bit* are needed
+     * beyond the returned digit position.  If the discarded portion of the input
+     * is sufficiently large, the returned digit string is incremented.  In round
+     * to nearest even, this threshold to increment occurs near the half-way
+     * point between digits.  The sticky bit records if there are any remaining
+     * trailing digits of the exact input value in the new format; the sticky bit
+     * is consulted only in close to half-way rounding cases.
+     *
+     * Given the computation of the digit and bit values, rounding is then
+     * reduced to a table lookup problem.  For decimal, the even/odd cases look
+     * like this:
+     *
+     * Last   Round   Sticky
+     * 6      5       0      => 6   // exactly halfway, return even digit.
+     * 6      5       1      => 7   // a little bit more than halfway, round up.
+     * 7      5       0      => 8   // exactly halfway, round up to even.
+     * 7      5       1      => 8   // a little bit more than halfway, round up.
+     * With analogous entries for other even and odd last-returned digits.
+     *
+     * However, decimal negative powers of 5 smaller than 0.5 are *not* exactly
+     * representable as binary fraction.  In particular, 0.005 (the round limit
+     * for a two-digit scale) and 0.0005 (the round limit for a three-digit
+     * scale) are not representable. Therefore, for input values near these cases
+     * the sticky bit is known to be set which reduces the rounding logic to:
+     *
+     * Last   Round   Sticky
+     * 6      5       1      => 7   // a little bit more than halfway, round up.
+     * 7      5       1      => 8   // a little bit more than halfway, round up.
+     *
+     * In other words, if the round digit is 5, the sticky bit is known to be
+     * set.  If the round digit is something other than 5, the sticky bit is not
+     * relevant.  Therefore, some of the logic about whether or not to increment
+     * the destination *decimal* value can occur based on tests of *binary*
+     * computations of the binary input number.
+     */
+
+    /**
+     * Check validity of using fast-path for this instance. If fast-path is valid
+     * for this instance, sets fast-path state as true and initializes fast-path
+     * utility fields as needed.
+     *
+     * This method is supposed to be called rarely, otherwise that will break the
+     * fast-path performance. That means avoiding frequent changes of the
+     * properties of the instance, since for most properties, each time a change
+     * happens, a call to this method is needed at the next format call.
+     *
+     * FAST-PATH RULES:
+     *  Similar to the default DecimalFormat instantiation case.
+     *  More precisely:
+     *  - HALF_EVEN rounding mode,
+     *  - isGroupingUsed() is true,
+     *  - groupingSize of 3,
+     *  - multiplier is 1,
+     *  - Decimal separator not mandatory,
+     *  - No use of exponential notation,
+     *  - minimumIntegerDigits is exactly 1 and maximumIntegerDigits at least 10
+     *  - For number of fractional digits, the exact values found in the default case:
+     *     Currency : min = max = 2.
+     *     Decimal  : min = 0. max = 3.
+     *
+     */
+    private void checkAndSetFastPathStatus() {
+
+        boolean fastPathWasOn = isFastPath;
+
+        if ((roundingMode == RoundingMode.HALF_EVEN) &&
+            (isGroupingUsed()) &&
+            (groupingSize == 3) &&
+            (multiplier == 1) &&
+            (!decimalSeparatorAlwaysShown) &&
+            (!useExponentialNotation)) {
+
+            // The fast-path algorithm is semi-hardcoded against
+            //  minimumIntegerDigits and maximumIntegerDigits.
+            isFastPath = ((minimumIntegerDigits == 1) &&
+                          (maximumIntegerDigits >= 10));
+
+            // The fast-path algorithm is hardcoded against
+            //  minimumFractionDigits and maximumFractionDigits.
+            if (isFastPath) {
+                if (isCurrencyFormat) {
+                    if ((minimumFractionDigits != 2) ||
+                        (maximumFractionDigits != 2))
+                        isFastPath = false;
+                } else if ((minimumFractionDigits != 0) ||
+                           (maximumFractionDigits != 3))
+                    isFastPath = false;
+            }
+        } else
+            isFastPath = false;
+
+        // Since some instance properties may have changed while still falling
+        // in the fast-path case, we need to reinitialize fastPathData anyway.
+        if (isFastPath) {
+            // We need to instantiate fastPathData if not already done.
+            if (fastPathData == null)
+                fastPathData = new FastPathData();
+
+            // Sets up the locale specific constants used when formatting.
+            // '0' is our default representation of zero.
+            fastPathData.zeroDelta = symbols.getZeroDigit() - '0';
+            fastPathData.groupingChar = symbols.getGroupingSeparator();
+
+            // Sets up fractional constants related to currency/decimal pattern.
+            fastPathData.fractionalMaxIntBound = (isCurrencyFormat) ? 99 : 999;
+            fastPathData.fractionalScaleFactor = (isCurrencyFormat) ? 100.0d : 1000.0d;
+
+            // Records the need for adding prefix or suffix
+            fastPathData.positiveAffixesRequired =
+                (positivePrefix.length() != 0) || (positiveSuffix.length() != 0);
+            fastPathData.negativeAffixesRequired =
+                (negativePrefix.length() != 0) || (negativeSuffix.length() != 0);
+
+            // Creates a cached char container for result, with max possible size.
+            int maxNbIntegralDigits = 10;
+            int maxNbGroups = 3;
+            int containerSize =
+                Math.max(positivePrefix.length(), negativePrefix.length()) +
+                maxNbIntegralDigits + maxNbGroups + 1 + maximumFractionDigits +
+                Math.max(positiveSuffix.length(), negativeSuffix.length());
+
+            fastPathData.fastPathContainer = new char[containerSize];
+
+            // Sets up prefix and suffix char arrays constants.
+            fastPathData.charsPositiveSuffix = positiveSuffix.toCharArray();
+            fastPathData.charsNegativeSuffix = negativeSuffix.toCharArray();
+            fastPathData.charsPositivePrefix = positivePrefix.toCharArray();
+            fastPathData.charsNegativePrefix = negativePrefix.toCharArray();
+
+            // Sets up fixed index positions for integral and fractional digits.
+            // Sets up decimal point in cached result container.
+            int longestPrefixLength =
+                Math.max(positivePrefix.length(), negativePrefix.length());
+            int decimalPointIndex =
+                maxNbIntegralDigits + maxNbGroups + longestPrefixLength;
+
+            fastPathData.integralLastIndex    = decimalPointIndex - 1;
+            fastPathData.fractionalFirstIndex = decimalPointIndex + 1;
+            fastPathData.fastPathContainer[decimalPointIndex] =
+                isCurrencyFormat ?
+                symbols.getMonetaryDecimalSeparator() :
+                symbols.getDecimalSeparator();
+
+        } else if (fastPathWasOn) {
+            // Previous state was fast-path and is no more.
+            // Resets cached array constants.
+            fastPathData.fastPathContainer = null;
+            fastPathData.charsPositiveSuffix = null;
+            fastPathData.charsNegativeSuffix = null;
+            fastPathData.charsPositivePrefix = null;
+            fastPathData.charsNegativePrefix = null;
+        }
+
+        fastPathCheckNeeded = false;
+    }
+
+    /**
+     * Returns true if rounding-up must be done on {@code scaledFractionalPartAsInt},
+     * false otherwise.
+     *
+     * This is a utility method that takes correct half-even rounding decision on
+     * passed fractional value at the scaled decimal point (2 digits for currency
+     * case and 3 for decimal case), when the approximated fractional part after
+     * scaled decimal point is exactly 0.5d.  This is done by means of exact
+     * calculations on the {@code fractionalPart} floating-point value.
+     *
+     * This method is supposed to be called by private {@code fastDoubleFormat}
+     * method only.
+     *
+     * The algorithms used for the exact calculations are :
+     *
+     * The <b><i>FastTwoSum</i></b> algorithm, from T.J.Dekker, described in the
+     * papers  "<i>A  Floating-Point   Technique  for  Extending  the  Available
+     * Precision</i>"  by Dekker, and  in "<i>Adaptive  Precision Floating-Point
+     * Arithmetic and Fast Robust Geometric Predicates</i>" from J.Shewchuk.
+     *
+     * A modified version of <b><i>Sum2S</i></b> cascaded summation described in
+     * "<i>Accurate Sum and Dot Product</i>" from Takeshi Ogita and All.  As
+     * Ogita says in this paper this is an equivalent of the Kahan-Babuska's
+     * summation algorithm because we order the terms by magnitude before summing
+     * them. For this reason we can use the <i>FastTwoSum</i> algorithm rather
+     * than the more expensive Knuth's <i>TwoSum</i>.
+     *
+     * We do this to avoid a more expensive exact "<i>TwoProduct</i>" algorithm,
+     * like those described in Shewchuk's paper above. See comments in the code
+     * below.
+     *
+     * @param  fractionalPart The  fractional value  on which  we  take rounding
+     * decision.
+     * @param scaledFractionalPartAsInt The integral part of the scaled
+     * fractional value.
+     *
+     * @return the decision that must be taken regarding half-even rounding.
+     */
+    private boolean exactRoundUp(double fractionalPart,
+                                 int scaledFractionalPartAsInt) {
+
+        /* exactRoundUp() method is called by fastDoubleFormat() only.
+         * The precondition expected to be verified by the passed parameters is :
+         * scaledFractionalPartAsInt ==
+         *     (int) (fractionalPart * fastPathData.fractionalScaleFactor).
+         * This is ensured by fastDoubleFormat() code.
+         */
+
+        /* We first calculate roundoff error made by fastDoubleFormat() on
+         * the scaled fractional part. We do this with exact calculation on the
+         * passed fractionalPart. Rounding decision will then be taken from roundoff.
+         */
+
+        /* ---- TwoProduct(fractionalPart, scale factor (i.e. 1000.0d or 100.0d)).
+         *
+         * The below is an optimized exact "TwoProduct" calculation of passed
+         * fractional part with scale factor, using Ogita's Sum2S cascaded
+         * summation adapted as Kahan-Babuska equivalent by using FastTwoSum
+         * (much faster) rather than Knuth's TwoSum.
+         *
+         * We can do this because we order the summation from smallest to
+         * greatest, so that FastTwoSum can be used without any additional error.
+         *
+         * The "TwoProduct" exact calculation needs 17 flops. We replace this by
+         * a cascaded summation of FastTwoSum calculations, each involving an
+         * exact multiply by a power of 2.
+         *
+         * Doing so saves overall 4 multiplications and 1 addition compared to
+         * using traditional "TwoProduct".
+         *
+         * The scale factor is either 100 (currency case) or 1000 (decimal case).
+         * - when 1000, we replace it by (1024 - 16 - 8) = 1000.
+         * - when 100,  we replace it by (128  - 32 + 4) =  100.
+         * Every multiplication by a power of 2 (1024, 128, 32, 16, 8, 4) is exact.
+         *
+         */
+        double approxMax;    // Will always be positive.
+        double approxMedium; // Will always be negative.
+        double approxMin;
+
+        double fastTwoSumApproximation = 0.0d;
+        double fastTwoSumRoundOff = 0.0d;
+        double bVirtual = 0.0d;
+
+        if (isCurrencyFormat) {
+            // Scale is 100 = 128 - 32 + 4.
+            // Multiply by 2**n is a shift. No roundoff. No error.
+            approxMax    = fractionalPart * 128.00d;
+            approxMedium = - (fractionalPart * 32.00d);
+            approxMin    = fractionalPart * 4.00d;
+        } else {
+            // Scale is 1000 = 1024 - 16 - 8.
+            // Multiply by 2**n is a shift. No roundoff. No error.
+            approxMax    = fractionalPart * 1024.00d;
+            approxMedium = - (fractionalPart * 16.00d);
+            approxMin    = - (fractionalPart * 8.00d);
+        }
+
+        // Shewchuk/Dekker's FastTwoSum(approxMedium, approxMin).
+        assert(-approxMedium >= Math.abs(approxMin));
+        fastTwoSumApproximation = approxMedium + approxMin;
+        bVirtual = fastTwoSumApproximation - approxMedium;
+        fastTwoSumRoundOff = approxMin - bVirtual;
+        double approxS1 = fastTwoSumApproximation;
+        double roundoffS1 = fastTwoSumRoundOff;
+
+        // Shewchuk/Dekker's FastTwoSum(approxMax, approxS1);
+        assert(approxMax >= Math.abs(approxS1));
+        fastTwoSumApproximation = approxMax + approxS1;
+        bVirtual = fastTwoSumApproximation - approxMax;
+        fastTwoSumRoundOff = approxS1 - bVirtual;
+        double roundoff1000 = fastTwoSumRoundOff;
+        double approx1000 = fastTwoSumApproximation;
+        double roundoffTotal = roundoffS1 + roundoff1000;
+
+        // Shewchuk/Dekker's FastTwoSum(approx1000, roundoffTotal);
+        assert(approx1000 >= Math.abs(roundoffTotal));
+        fastTwoSumApproximation = approx1000 + roundoffTotal;
+        bVirtual = fastTwoSumApproximation - approx1000;
+
+        // Now we have got the roundoff for the scaled fractional
+        double scaledFractionalRoundoff = roundoffTotal - bVirtual;
+
+        // ---- TwoProduct(fractionalPart, scale (i.e. 1000.0d or 100.0d)) end.
+
+        /* ---- Taking the rounding decision
+         *
+         * We take rounding decision based on roundoff and half-even rounding
+         * rule.
+         *
+         * The above TwoProduct gives us the exact roundoff on the approximated
+         * scaled fractional, and we know that this approximation is exactly
+         * 0.5d, since that has already been tested by the caller
+         * (fastDoubleFormat).
+         *
+         * Decision comes first from the sign of the calculated exact roundoff.
+         * - Since being exact roundoff, it cannot be positive with a scaled
+         *   fractional less than 0.5d, as well as negative with a scaled
+         *   fractional greater than 0.5d. That leaves us with following 3 cases.
+         * - positive, thus scaled fractional == 0.500....0fff ==> round-up.
+         * - negative, thus scaled fractional == 0.499....9fff ==> don't round-up.
+         * - is zero,  thus scaled fractioanl == 0.5 ==> half-even rounding applies :
+         *    we round-up only if the integral part of the scaled fractional is odd.
+         *
+         */
+        if (scaledFractionalRoundoff > 0.0) {
+            return true;
+        } else if (scaledFractionalRoundoff < 0.0) {
+            return false;
+        } else if ((scaledFractionalPartAsInt & 1) != 0) {
+            return true;
+        }
+
+        return false;
+
+        // ---- Taking the rounding decision end
+    }
+
+    /**
+     * Collects integral digits from passed {@code number}, while setting
+     * grouping chars as needed. Updates {@code firstUsedIndex} accordingly.
+     *
+     * Loops downward starting from {@code backwardIndex} position (inclusive).
+     *
+     * @param number  The int value from which we collect digits.
+     * @param digitsBuffer The char array container where digits and grouping chars
+     *  are stored.
+     * @param backwardIndex the position from which we start storing digits in
+     *  digitsBuffer.
+     *
+     */
+    private void collectIntegralDigits(int number,
+                                       char[] digitsBuffer,
+                                       int backwardIndex) {
+        int index = backwardIndex;
+        int q;
+        int r;
+        while (number > 999) {
+            // Generates 3 digits per iteration.
+            q = number / 1000;
+            r = number - (q << 10) + (q << 4) + (q << 3); // -1024 +16 +8 = 1000.
+            number = q;
+
+            digitsBuffer[index--] = DigitArrays.DigitOnes1000[r];
+            digitsBuffer[index--] = DigitArrays.DigitTens1000[r];
+            digitsBuffer[index--] = DigitArrays.DigitHundreds1000[r];
+            digitsBuffer[index--] = fastPathData.groupingChar;
+        }
+
+        // Collects last 3 or less digits.
+        digitsBuffer[index] = DigitArrays.DigitOnes1000[number];
+        if (number > 9) {
+            digitsBuffer[--index]  = DigitArrays.DigitTens1000[number];
+            if (number > 99)
+                digitsBuffer[--index]   = DigitArrays.DigitHundreds1000[number];
+        }
+
+        fastPathData.firstUsedIndex = index;
+    }
+
+    /**
+     * Collects the 2 (currency) or 3 (decimal) fractional digits from passed
+     * {@code number}, starting at {@code startIndex} position
+     * inclusive.  There is no punctuation to set here (no grouping chars).
+     * Updates {@code fastPathData.lastFreeIndex} accordingly.
+     *
+     *
+     * @param number  The int value from which we collect digits.
+     * @param digitsBuffer The char array container where digits are stored.
+     * @param startIndex the position from which we start storing digits in
+     *  digitsBuffer.
+     *
+     */
+    private void collectFractionalDigits(int number,
+                                         char[] digitsBuffer,
+                                         int startIndex) {
+        int index = startIndex;
+
+        char digitOnes = DigitArrays.DigitOnes1000[number];
+        char digitTens = DigitArrays.DigitTens1000[number];
+
+        if (isCurrencyFormat) {
+            // Currency case. Always collects fractional digits.
+            digitsBuffer[index++] = digitTens;
+            digitsBuffer[index++] = digitOnes;
+        } else if (number != 0) {
+            // Decimal case. Hundreds will always be collected
+            digitsBuffer[index++] = DigitArrays.DigitHundreds1000[number];
+
+            // Ending zeros won't be collected.
+            if (digitOnes != '0') {
+                digitsBuffer[index++] = digitTens;
+                digitsBuffer[index++] = digitOnes;
+            } else if (digitTens != '0')
+                digitsBuffer[index++] = digitTens;
+
+        } else
+            // This is decimal pattern and fractional part is zero.
+            // We must remove decimal point from result.
+            index--;
+
+        fastPathData.lastFreeIndex = index;
+    }
+
+    /**
+     * Internal utility.
+     * Adds the passed {@code prefix} and {@code suffix} to {@code container}.
+     *
+     * @param container  Char array container which to prepend/append the
+     *  prefix/suffix.
+     * @param prefix     Char sequence to prepend as a prefix.
+     * @param suffix     Char sequence to append as a suffix.
+     *
+     */
+    //    private void addAffixes(boolean isNegative, char[] container) {
+    private void addAffixes(char[] container, char[] prefix, char[] suffix) {
+
+        // We add affixes only if needed (affix length > 0).
+        int pl = prefix.length;
+        int sl = suffix.length;
+        if (pl != 0) prependPrefix(prefix, pl, container);
+        if (sl != 0) appendSuffix(suffix, sl, container);
+
+    }
+
+    /**
+     * Prepends the passed {@code prefix} chars to given result
+     * {@code container}.  Updates {@code fastPathData.firstUsedIndex}
+     * accordingly.
+     *
+     * @param prefix The prefix characters to prepend to result.
+     * @param len The number of chars to prepend.
+     * @param container Char array container which to prepend the prefix
+     */
+    private void prependPrefix(char[] prefix,
+                               int len,
+                               char[] container) {
+
+        fastPathData.firstUsedIndex -= len;
+        int startIndex = fastPathData.firstUsedIndex;
+
+        // If prefix to prepend is only 1 char long, just assigns this char.
+        // If prefix is less or equal 4, we use a dedicated algorithm that
+        //  has shown to run faster than System.arraycopy.
+        // If more than 4, we use System.arraycopy.
+        if (len == 1)
+            container[startIndex] = prefix[0];
+        else if (len <= 4) {
+            int dstLower = startIndex;
+            int dstUpper = dstLower + len - 1;
+            int srcUpper = len - 1;
+            container[dstLower] = prefix[0];
+            container[dstUpper] = prefix[srcUpper];
+
+            if (len > 2)
+                container[++dstLower] = prefix[1];
+            if (len == 4)
+                container[--dstUpper] = prefix[2];
+        } else
+            System.arraycopy(prefix, 0, container, startIndex, len);
+    }
+
+    /**
+     * Appends the passed {@code suffix} chars to given result
+     * {@code container}.  Updates {@code fastPathData.lastFreeIndex}
+     * accordingly.
+     *
+     * @param suffix The suffix characters to append to result.
+     * @param len The number of chars to append.
+     * @param container Char array container which to append the suffix
+     */
+    private void appendSuffix(char[] suffix,
+                              int len,
+                              char[] container) {
+
+        int startIndex = fastPathData.lastFreeIndex;
+
+        // If suffix to append is only 1 char long, just assigns this char.
+        // If suffix is less or equal 4, we use a dedicated algorithm that
+        //  has shown to run faster than System.arraycopy.
+        // If more than 4, we use System.arraycopy.
+        if (len == 1)
+            container[startIndex] = suffix[0];
+        else if (len <= 4) {
+            int dstLower = startIndex;
+            int dstUpper = dstLower + len - 1;
+            int srcUpper = len - 1;
+            container[dstLower] = suffix[0];
+            container[dstUpper] = suffix[srcUpper];
+
+            if (len > 2)
+                container[++dstLower] = suffix[1];
+            if (len == 4)
+                container[--dstUpper] = suffix[2];
+        } else
+            System.arraycopy(suffix, 0, container, startIndex, len);
+
+        fastPathData.lastFreeIndex += len;
+    }
+
+    /**
+     * Converts digit chars from {@code digitsBuffer} to current locale.
+     *
+     * Must be called before adding affixes since we refer to
+     * {@code fastPathData.firstUsedIndex} and {@code fastPathData.lastFreeIndex},
+     * and do not support affixes (for speed reason).
+     *
+     * We loop backward starting from last used index in {@code fastPathData}.
+     *
+     * @param digitsBuffer The char array container where the digits are stored.
+     */
+    private void localizeDigits(char[] digitsBuffer) {
+
+        // We will localize only the digits, using the groupingSize,
+        // and taking into account fractional part.
+
+        // First take into account fractional part.
+        int digitsCounter =
+            fastPathData.lastFreeIndex - fastPathData.fractionalFirstIndex;
+
+        // The case when there is no fractional digits.
+        if (digitsCounter < 0)
+            digitsCounter = groupingSize;
+
+        // Only the digits remains to localize.
+        for (int cursor = fastPathData.lastFreeIndex - 1;
+             cursor >= fastPathData.firstUsedIndex;
+             cursor--) {
+            if (digitsCounter != 0) {
+                // This is a digit char, we must localize it.
+                digitsBuffer[cursor] += fastPathData.zeroDelta;
+                digitsCounter--;
+            } else {
+                // Decimal separator or grouping char. Reinit counter only.
+                digitsCounter = groupingSize;
+            }
+        }
+    }
+
+    /**
+     * This is the main entry point for the fast-path format algorithm.
+     *
+     * At this point we are sure to be in the expected conditions to run it.
+     * This algorithm builds the formatted result and puts it in the dedicated
+     * {@code fastPathData.fastPathContainer}.
+     *
+     * @param d the double value to be formatted.
+     * @param negative Flag precising if {@code d} is negative.
+     */
+    private void fastDoubleFormat(double d,
+                                  boolean negative) {
+
+        char[] container = fastPathData.fastPathContainer;
+
+        /*
+         * The principle of the algorithm is to :
+         * - Break the passed double into its integral and fractional parts
+         *    converted into integers.
+         * - Then decide if rounding up must be applied or not by following
+         *    the half-even rounding rule, first using approximated scaled
+         *    fractional part.
+         * - For the difficult cases (approximated scaled fractional part
+         *    being exactly 0.5d), we refine the rounding decision by calling
+         *    exactRoundUp utility method that both calculates the exact roundoff
+         *    on the approximation and takes correct rounding decision.
+         * - We round-up the fractional part if needed, possibly propagating the
+         *    rounding to integral part if we meet a "all-nine" case for the
+         *    scaled fractional part.
+         * - We then collect digits from the resulting integral and fractional
+         *   parts, also setting the required grouping chars on the fly.
+         * - Then we localize the collected digits if needed, and
+         * - Finally prepend/append prefix/suffix if any is needed.
+         */
+
+        // Exact integral part of d.
+        int integralPartAsInt = (int) d;
+
+        // Exact fractional part of d (since we subtract it's integral part).
+        double exactFractionalPart = d - (double) integralPartAsInt;
+
+        // Approximated scaled fractional part of d (due to multiplication).
+        double scaledFractional =
+            exactFractionalPart * fastPathData.fractionalScaleFactor;
+
+        // Exact integral part of scaled fractional above.
+        int fractionalPartAsInt = (int) scaledFractional;
+
+        // Exact fractional part of scaled fractional above.
+        scaledFractional = scaledFractional - (double) fractionalPartAsInt;
+
+        // Only when scaledFractional is exactly 0.5d do we have to do exact
+        // calculations and take fine-grained rounding decision, since
+        // approximated results above may lead to incorrect decision.
+        // Otherwise comparing against 0.5d (strictly greater or less) is ok.
+        boolean roundItUp = false;
+        if (scaledFractional >= 0.5d) {
+            if (scaledFractional == 0.5d)
+                // Rounding need fine-grained decision.
+                roundItUp = exactRoundUp(exactFractionalPart, fractionalPartAsInt);
+            else
+                roundItUp = true;
+
+            if (roundItUp) {
+                // Rounds up both fractional part (and also integral if needed).
+                if (fractionalPartAsInt < fastPathData.fractionalMaxIntBound) {
+                    fractionalPartAsInt++;
+                } else {
+                    // Propagates rounding to integral part since "all nines" case.
+                    fractionalPartAsInt = 0;
+                    integralPartAsInt++;
+                }
+            }
+        }
+
+        // Collecting digits.
+        collectFractionalDigits(fractionalPartAsInt, container,
+                                fastPathData.fractionalFirstIndex);
+        collectIntegralDigits(integralPartAsInt, container,
+                              fastPathData.integralLastIndex);
+
+        // Localizing digits.
+        if (fastPathData.zeroDelta != 0)
+            localizeDigits(container);
+
+        // Adding prefix and suffix.
+        if (negative) {
+            if (fastPathData.negativeAffixesRequired)
+                addAffixes(container,
+                           fastPathData.charsNegativePrefix,
+                           fastPathData.charsNegativeSuffix);
+        } else if (fastPathData.positiveAffixesRequired)
+            addAffixes(container,
+                       fastPathData.charsPositivePrefix,
+                       fastPathData.charsPositiveSuffix);
+    }
+
+    /**
+     * A fast-path shortcut of format(double) to be called by NumberFormat, or by
+     * format(double, ...) public methods.
+     *
+     * If instance can be applied fast-path and passed double is not NaN or
+     * Infinity, is in the integer range, we call {@code fastDoubleFormat}
+     * after changing {@code d} to its positive value if necessary.
+     *
+     * Otherwise returns null by convention since fast-path can't be exercized.
+     *
+     * @param d The double value to be formatted
+     *
+     * @return the formatted result for {@code d} as a string.
+     */
+    String fastFormat(double d) {
+        // (Re-)Evaluates fast-path status if needed.
+        if (fastPathCheckNeeded)
+            checkAndSetFastPathStatus();
+
+        if (!isFastPath )
+            // DecimalFormat instance is not in a fast-path state.
+            return null;
+
+        if (!Double.isFinite(d))
+            // Should not use fast-path for Infinity and NaN.
+            return null;
+
+        // Extracts and records sign of double value, possibly changing it
+        // to a positive one, before calling fastDoubleFormat().
+        boolean negative = false;
+        if (d < 0.0d) {
+            negative = true;
+            d = -d;
+        } else if (d == 0.0d) {
+            negative = (Math.copySign(1.0d, d) == -1.0d);
+            d = +0.0d;
+        }
+
+        if (d > MAX_INT_AS_DOUBLE)
+            // Filters out values that are outside expected fast-path range
+            return null;
+        else
+            fastDoubleFormat(d, negative);
+
+        // Returns a new string from updated fastPathContainer.
+        return new String(fastPathData.fastPathContainer,
+                          fastPathData.firstUsedIndex,
+                          fastPathData.lastFreeIndex - fastPathData.firstUsedIndex);
+
+    }
+
+    // ======== End fast-path formating logic for double =========================
+
     /**
      * Complete the formatting of a finite number.  On entry, the digitList must
      * be filled in with the correct digits.
@@ -1168,8 +1898,7 @@
         if (isNegative) {
             append(result, negativeSuffix, delegate,
                    getNegativeSuffixFieldPositions(), Field.SIGN);
-        }
-        else {
+        } else {
             append(result, positiveSuffix, delegate,
                    getPositiveSuffixFieldPositions(), Field.SIGN);
         }
@@ -1557,8 +2286,7 @@
                         sawExponent = true;
                     }
                     break; // Whether we fail or succeed, we exit this loop
-                }
-                else {
+                } else {
                     break;
                 }
             }
@@ -1653,6 +2381,7 @@
             // don't allow multiple references
             symbols = (DecimalFormatSymbols) newSymbols.clone();
             expandAffixes();
+            fastPathCheckNeeded = true;
         } catch (Exception foo) {
             // should never happen
         }
@@ -1674,6 +2403,7 @@
         positivePrefix = newValue;
         posPrefixPattern = null;
         positivePrefixFieldPositions = null;
+        fastPathCheckNeeded = true;
     }
 
     /**
@@ -1688,8 +2418,7 @@
         if (positivePrefixFieldPositions == null) {
             if (posPrefixPattern != null) {
                 positivePrefixFieldPositions = expandAffix(posPrefixPattern);
-            }
-            else {
+            } else {
                 positivePrefixFieldPositions = EmptyFieldPositionArray;
             }
         }
@@ -1711,6 +2440,7 @@
     public void setNegativePrefix (String newValue) {
         negativePrefix = newValue;
         negPrefixPattern = null;
+        fastPathCheckNeeded = true;
     }
 
     /**
@@ -1725,8 +2455,7 @@
         if (negativePrefixFieldPositions == null) {
             if (negPrefixPattern != null) {
                 negativePrefixFieldPositions = expandAffix(negPrefixPattern);
-            }
-            else {
+            } else {
                 negativePrefixFieldPositions = EmptyFieldPositionArray;
             }
         }
@@ -1748,6 +2477,7 @@
     public void setPositiveSuffix (String newValue) {
         positiveSuffix = newValue;
         posSuffixPattern = null;
+        fastPathCheckNeeded = true;
     }
 
     /**
@@ -1762,8 +2492,7 @@
         if (positiveSuffixFieldPositions == null) {
             if (posSuffixPattern != null) {
                 positiveSuffixFieldPositions = expandAffix(posSuffixPattern);
-            }
-            else {
+            } else {
                 positiveSuffixFieldPositions = EmptyFieldPositionArray;
             }
         }
@@ -1785,6 +2514,7 @@
     public void setNegativeSuffix (String newValue) {
         negativeSuffix = newValue;
         negSuffixPattern = null;
+        fastPathCheckNeeded = true;
     }
 
     /**
@@ -1799,8 +2529,7 @@
         if (negativeSuffixFieldPositions == null) {
             if (negSuffixPattern != null) {
                 negativeSuffixFieldPositions = expandAffix(negSuffixPattern);
-            }
-            else {
+            } else {
                 negativeSuffixFieldPositions = EmptyFieldPositionArray;
             }
         }
@@ -1834,6 +2563,16 @@
         multiplier = newValue;
         bigDecimalMultiplier = null;
         bigIntegerMultiplier = null;
+        fastPathCheckNeeded = true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setGroupingUsed(boolean newValue) {
+        super.setGroupingUsed(newValue);
+        fastPathCheckNeeded = true;
     }
 
     /**
@@ -1860,6 +2599,7 @@
      */
     public void setGroupingSize (int newValue) {
         groupingSize = (byte)newValue;
+        fastPathCheckNeeded = true;
     }
 
     /**
@@ -1878,6 +2618,7 @@
      */
     public void setDecimalSeparatorAlwaysShown(boolean newValue) {
         decimalSeparatorAlwaysShown = newValue;
+        fastPathCheckNeeded = true;
     }
 
     /**
@@ -1908,6 +2649,20 @@
         DecimalFormat other = (DecimalFormat) super.clone();
         other.symbols = (DecimalFormatSymbols) symbols.clone();
         other.digitList = (DigitList) digitList.clone();
+
+        // Fast-path is almost stateless algorithm. The only logical state is the
+        // isFastPath flag. In addition fastPathCheckNeeded is a sentinel flag
+        // that forces recalculation of all fast-path fields when set to true.
+        //
+        // There is thus no need to clone all the fast-path fields.
+        // We just only need to set fastPathCheckNeeded to true when cloning,
+        // and init fastPathData to null as if it were a truly new instance.
+        // Every fast-path field will be recalculated (only once) at next usage of
+        // fast-path algorithm.
+        other.fastPathCheckNeeded = true;
+        other.isFastPath = false;
+        other.fastPathData = null;
+
         return other;
     }
 
@@ -1917,8 +2672,10 @@
     @Override
     public boolean equals(Object obj)
     {
-        if (obj == null) return false;
-        if (!super.equals(obj)) return false; // super does class check
+        if (obj == null)
+            return false;
+        if (!super.equals(obj))
+            return false; // super does class check
         DecimalFormat other = (DecimalFormat) obj;
         return ((posPrefixPattern == other.posPrefixPattern &&
                  positivePrefix.equals(other.positivePrefix))
@@ -2206,8 +2963,7 @@
                 || affix.indexOf(symbols.getPatternSeparator()) >= 0
                 || affix.indexOf(symbols.getMinusSign()) >= 0
                 || affix.indexOf(CURRENCY_SIGN) >= 0;
-        }
-        else {
+        } else {
             needQuote = affix.indexOf(PATTERN_ZERO_DIGIT) >= 0
                 || affix.indexOf(PATTERN_GROUPING_SEPARATOR) >= 0
                 || affix.indexOf(PATTERN_DECIMAL_SEPARATOR) >= 0
@@ -2694,6 +3450,7 @@
             super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
                 DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);
         }
+        fastPathCheckNeeded = true;
     }
 
     /**
@@ -2714,6 +3471,7 @@
             super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
                 DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);
         }
+        fastPathCheckNeeded = true;
     }
 
     /**
@@ -2734,6 +3492,7 @@
             super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
                 DOUBLE_FRACTION_DIGITS : minimumFractionDigits);
         }
+        fastPathCheckNeeded = true;
     }
 
     /**
@@ -2754,6 +3513,7 @@
             super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
                 DOUBLE_FRACTION_DIGITS : maximumFractionDigits);
         }
+        fastPathCheckNeeded = true;
     }
 
     /**
@@ -2843,6 +3603,7 @@
                 expandAffixes();
             }
         }
+        fastPathCheckNeeded = true;
     }
 
     /**
@@ -2873,6 +3634,7 @@
 
         this.roundingMode = roundingMode;
         digitList.setRoundingMode(roundingMode);
+        fastPathCheckNeeded = true;
     }
 
     /**
@@ -2924,6 +3686,12 @@
         stream.defaultReadObject();
         digitList = new DigitList();
 
+        // We force complete fast-path reinitialization when the instance is
+        // deserialized. See clone() comment on fastPathCheckNeeded.
+        fastPathCheckNeeded = true;
+        isFastPath = false;
+        fastPathData = null;
+
         if (serialVersionOnStream < 4) {
             setRoundingMode(RoundingMode.HALF_EVEN);
         }
@@ -3195,6 +3963,77 @@
      */
     private RoundingMode roundingMode = RoundingMode.HALF_EVEN;
 
+    // ------ DecimalFormat fields for fast-path for double algorithm  ------
+
+    /**
+     * Helper inner utility class for storing the data used in the fast-path
+     * algorithm. Almost all fields related to fast-path are encapsulated in
+     * this class.
+     *
+     * Any {@code DecimalFormat} instance has a {@code fastPathData}
+     * reference field that is null unless both the properties of the instance
+     * are such that the instance is in the "fast-path" state, and a format call
+     * has been done at least once while in this state.
+     *
+     * Almost all fields are related to the "fast-path" state only and don't
+     * change until one of the instance properties is changed.
+     *
+     * {@code firstUsedIndex} and {@code lastFreeIndex} are the only
+     * two fields that are used and modified while inside a call to
+     * {@code fastDoubleFormat}.
+     *
+     */
+    private static class FastPathData {
+        // --- Temporary fields used in fast-path, shared by several methods.
+
+        /** The first unused index at the end of the formatted result. */
+        int lastFreeIndex;
+
+        /** The first used index at the beginning of the formatted result */
+        int firstUsedIndex;
+
+        // --- State fields related to fast-path status. Changes due to a
+        //     property change only. Set by checkAndSetFastPathStatus() only.
+
+        /** Difference between locale zero and default zero representation. */
+        int  zeroDelta;
+
+        /** Locale char for grouping separator. */
+        char groupingChar;
+
+        /**  Fixed index position of last integral digit of formatted result */
+        int integralLastIndex;
+
+        /**  Fixed index position of first fractional digit of formatted result */
+        int fractionalFirstIndex;
+
+        /** Fractional constants depending on decimal|currency state */
+        double fractionalScaleFactor;
+        int fractionalMaxIntBound;
+
+
+        /** The char array buffer that will contain the formatted result */
+        char[] fastPathContainer;
+
+        /** Suffixes recorded as char array for efficiency. */
+        char[] charsPositivePrefix;
+        char[] charsNegativePrefix;
+        char[] charsPositiveSuffix;
+        char[] charsNegativeSuffix;
+        boolean positiveAffixesRequired = true;
+        boolean negativeAffixesRequired = true;
+    }
+
+    /** The format fast-path status of the instance. Logical state. */
+    private transient boolean isFastPath = false;
+
+    /** Flag stating need of check and reinit fast-path status on next format call. */
+    private transient boolean fastPathCheckNeeded = true;
+
+    /** DecimalFormat reference to its FastPathData */
+    private transient FastPathData fastPathData;
+
+
     //----------------------------------------------------------------------
 
     static final int currentSerialVersion = 4;
@@ -3228,6 +4067,54 @@
     // CONSTANTS
     //----------------------------------------------------------------------
 
+    // ------ Fast-Path for double Constants ------
+
+    /** Maximum valid integer value for applying fast-path algorithm */
+    private static final double MAX_INT_AS_DOUBLE = (double) Integer.MAX_VALUE;
+
+    /**
+     * The digit arrays used in the fast-path methods for collecting digits.
+     * Using 3 constants arrays of chars ensures a very fast collection of digits
+     */
+    private static class DigitArrays {
+        static final char[] DigitOnes1000 = new char[1000];
+        static final char[] DigitTens1000 = new char[1000];
+        static final char[] DigitHundreds1000 = new char[1000];
+
+        // initialize on demand holder class idiom for arrays of digits
+        static {
+            int tenIndex = 0;
+            int hundredIndex = 0;
+            char digitOne = '0';
+            char digitTen = '0';
+            char digitHundred = '0';
+            for (int i = 0;  i < 1000; i++ ) {
+
+                DigitOnes1000[i] = digitOne;
+                if (digitOne == '9')
+                    digitOne = '0';
+                else
+                    digitOne++;
+
+                DigitTens1000[i] = digitTen;
+                if (i == (tenIndex + 9)) {
+                    tenIndex += 10;
+                    if (digitTen == '9')
+                        digitTen = '0';
+                    else
+                        digitTen++;
+                }
+
+                DigitHundreds1000[i] = digitHundred;
+                if (i == (hundredIndex + 99)) {
+                    digitHundred++;
+                    hundredIndex += 100;
+                }
+            }
+        }
+    }
+    // ------ Fast-Path for double Constants end ------
+
     // Constants for characters used in programmatic (unlocalized) patterns.
     private static final char       PATTERN_ZERO_DIGIT         = '0';
     private static final char       PATTERN_GROUPING_SEPARATOR = ',';
--- a/jdk/src/share/classes/java/text/NumberFormat.java	Mon Oct 01 15:36:57 2012 +0100
+++ b/jdk/src/share/classes/java/text/NumberFormat.java	Tue Oct 02 10:11:57 2012 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -286,10 +286,21 @@
      * @see java.text.Format#format
      */
     public final String format(double number) {
+        // Use fast-path for double result if that works
+        String result = fastFormat(number);
+        if (result != null)
+            return result;
+
         return format(number, new StringBuffer(),
                       DontCareFieldPosition.INSTANCE).toString();
     }
 
+    /*
+     * fastFormat() is supposed to be implemented in concrete subclasses only.
+     * Default implem always returns null.
+     */
+    String fastFormat(double number) { return null; }
+
    /**
      * Specialization of format.
      * @exception        ArithmeticException if rounding is needed with rounding
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DecimalFormat/FormatMicroBenchmark.java	Tue Oct 02 10:11:57 2012 +0100
@@ -0,0 +1,926 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7050528
+ * @summary Set of micro-benchmarks testing throughput of java.text.DecimalFormat.format()
+ * @author Olivier Lagneau
+ * @run main FormatMicroBenchmark
+ */
+
+/* This is a set of micro-benchmarks testing throughput of java.text.DecimalFormat.format().
+ * It never fails.
+ *
+ * Usage and arguments:
+ *  - Run with no argument skips the whole benchmark and exits.
+ *  - Run with "-help" as first argument calls the usage() method and exits.
+ *  - Run with "-doit" runs the benchmark with summary details.
+ *  - Run with "-verbose" provides additional details on the run.
+ *
+ * Example run :
+ *   java -Xms500m -Xmx500m -XX:NewSize=400m FormatMicroBenchmark -doit -verbose
+ *
+ * Running with jtreg:
+ *  The jtreg header "run" tag options+args must be changed to avoid skipping
+ *  the execution. here is an example of run options:
+ *  "main/othervm -Xms500m -Xmx500m -XX:NewSize=400m FormatMicroBenchmark -doit"
+ *
+ * Note:
+ *  - Vm options -Xms, -Xmx, -XX:NewSize must be set correctly for
+ *    getting reliable numbers. Otherwise GC activity may corrupt results.
+ *    As of jdk80b48 using "-Xms500m -Xmx500m -XX:NewSize=400m" covers
+ *    all cases.
+ *  - Optionally using "-XX:+printGC" option provides information that
+ *    helps checking any GC activity while benches are run.
+ *
+ * Vm Options:
+ *  - Vm options to use (as of jdk80b48):
+ *     fast-path case :     -Xms128m -Xmx128m -XX:NewSize=100m
+ *     non fast-path case:  -Xms500m -Xmx500m -XX:NewSize=400m
+ *    or use worst case (non fast-path above) with both types of algorithm.
+ *
+ *  - use -XX:+PrintGC to verify memory consumption of the benchmarks.
+ *    (See "Checking Memory Consumption" below).
+ *
+ * Description:
+ *
+ *  Fast-path algorithm for format(double...)  call stack is very different  of
+ *  the standard call stack. Where the  standard algorithm for formating double
+ *  uses internal class sun.misc.FloatingDecimal and its dtoa(double) method to
+ *  provide digits,  fast-path embeds its own  algorithm for  binary to decimal
+ *  string conversion.
+ *
+ *  FloatingDecimal always converts completely  the passed double to  a string.
+ *  Fast-path converts  only to the needed digits  since it follows constraints
+ *  on both the pattern rule,  the  DecimalFormat instance properties, and  the
+ *  passed double.
+ *
+ *  Micro benchmarks below measure  the throughput for formating double  values
+ *  using NumberFormat.format(double)  call stack.  The  standard DecimalFormat
+ *  call stack as well as the  fast-path algorithm implementation are sensitive
+ *  to the nature of the passed double values regarding throughput performance.
+ *
+ *  These benchmarks are useful both  for measuring the global performance gain
+ *  of fast-path and to check that any modification done on fast-path algorithm
+ *  does not bring any regression in the performance boost of fast-path.
+ *
+ *  Note  that these benchmarks  will provide numbers  without any knowledge of
+ *  the  implementation of DecimalFormat class. So  to check regression any run
+ *  should be compared to another reference run with  a previous JDK, wether or
+ *  not this previous reference JDK contains fast-path implementation.
+ *
+ *  The eight benchmarks below are dedicated to measure throughput on different
+ *  kinds of double that all fall in the fast-path case (all in Integer range):
+ *
+ *  - Integer case : used double values are all "integer-like" (ex: -12345.0).
+ *    This is the benchFormatInteger micro-benchmark.
+ *
+ *  - Fractional case : double values are "fractional" (ex: -0.12345).
+ *    This is the benchFormatFractional micro-benchmark.
+ *
+ *  - Small integral case : like Integer case but double values are all limited
+ *    in their magnitude, from -500.0 to 500.0 if the number of iterations N is
+ *    set to 500000.
+ *    This is the benchFormatSmallIntegral micro-benchmark.
+ *
+ *  - Fractional All Nines : doubles values have fractional part that is very
+ *    close to "999" (decimal pattern), or "99" (currency pattern),
+ *    or "0000...".
+ *    This is the benchFormatFractionalAllNines micro-benchmark.
+ *
+ *  - All Nines : double values are such that both integral and fractional
+ *    part consist only of '9' digits. None of these values are rounded up.
+ *    This is the benchFormatAllNines micro-benchmark.
+ *
+ *  - Fair simple case : calling J the loop variable and iterating over
+ *    the N number of iterations, used double values are computed as
+ *    d = (double) J + J*seed
+ *    where seed is a very small value that adds a fractional part and adds a
+ *    small number to integral part. Provides fairly distributed double values.
+ *    This is the benchFormatFairSimple micro-benchmark.
+ *
+ *  - Fair case : this is a combination of small integral case and fair simple
+ *    case. Double values are limited in their magnitude but follow a parabolic
+ *    curve y = x**2 / K, keeping large magnitude only for large values of J.
+ *    The intent is trying to reproduce a distribution of double values as could
+ *    be found in a business application, with most values in either the low
+ *    range or the high range.
+ *    This is the benchFormatFair micro-benchmark.
+ *
+ *  - Tie cases: values are very close to a tie case (iii...ii.fff5)
+ *    That is the worst situation that can happen for Fast-path algorithm when
+ *    considering throughput.
+ *    This is the benchFormatTie micro-benchmark.
+ *
+ *  For  all  of  the micro-benchmarks,  the  throughput load   of the eventual
+ *  additional computations inside the loop is calculated  prior to running the
+ *  benchmark, and provided in the output.  That may be  useful since this load
+ *  may vary for each architecture or machine configuration.
+ *
+ *  The "-verbose" flag,  when set, provides the  throughput  load numbers, the
+ *  time spent for  each run of  a benchmark, as  well as an estimation  of the
+ *  memory consumed  by the  runs.  Beware of  incremental  GCs, see  "Checking
+ *  Memory  Consumption" section below. Every run   should be done with correct
+ *  ms, mx, and NewSize vm options to get fully reliable numbers.
+ *
+ *  The output provides the  mean time needed for  a benchmark after the server
+ *  jit compiler has done its optimization work if  any. Thus only the last but
+ *  first three runs are taken into account in the time measurement (server jit
+ *  compiler shows  to have  done full  optimization  in  most cases  after the
+ *  second run, given a base number of iterations set to 500000).
+ *
+ *  The program cleans up memory (stabilizeMemory() method) between each run of
+ *  the benchmarks to make sure that  no garbage collection activity happens in
+ *  measurements. However that does not  preclude incremental GCs activity that
+ *  may  happen during the micro-benchmark if  -Xms, -Xmx, and NewSize options
+ *  have not been tuned and set correctly.
+ *
+ * Checking Memory Consumption:
+ *
+ *  For getting confidence  in the throughput numbers, there  must not give any
+ *  GC activity during the benchmark runs. That  means that specific VM options
+ *  related to memory must be tuned for any given implementation of the JDK.
+ *
+ *  Running with "-verbose" arguments will provide  clues of the memory consumed
+ *  but  is   not enough,  since  any   unexpected  incremental  GC  may  lower
+ *  artificially the estimation of the memory consumption.
+ *
+ *  Options to  set are -Xms, -Xmx,  -XX:NewSize, plus -XX:+PrintGC to evaluate
+ *  correctly  the  values of  these options. When  running "-verbose", varying
+ *  numbers reported for memory consumption may  indicate bad choices for these
+ *  options.
+ *
+ *  For jdk80b25, fast-path shows a consuption of ~60Mbs for 500000 iterations
+ *  while a jdk without fast-path will consume ~260Mbs for each benchmark run.
+ *  Indeed these values will vary depending on the jdk used.
+ *
+ *  Correct option settings found jdk80b48 were :
+ *     fast-path :     -Xms128m -Xmx128m -XX:NewSize=100m
+ *     non fast-path : -Xms500m -Xmx500m -XX:NewSize=400m
+ *  Greater values can be provided safely but not smaller ones.
+ * ----------------------------------------------------------------------
+ */
+
+import java.util.*;
+import java.text.NumberFormat;
+import java.text.DecimalFormat;
+
+public class FormatMicroBenchmark {
+
+    // The number of times the bench method will be run (must be at least 4).
+    private static final int NB_RUNS = 20;
+
+    // The bench* methods below all iterates over [-MAX_RANGE , +MAX_RANGE] integer values.
+    private static final int MAX_RANGE = 500000;
+
+    // Flag for more details on each bench run (default is no).
+    private static boolean Verbose = false;
+
+    // Should we really execute the benches ? (no by default).
+    private static boolean DoIt = false;
+
+    // Prints out a message describing how to run the program.
+    private static void usage() {
+        System.out.println(
+            "This is a set of micro-benchmarks testing throughput of " +
+            "java.text.DecimalFormat.format(). It never fails.\n\n" +
+            "Usage and arguments:\n" +
+            " - Run with no argument skips the whole benchmark and exits.\n" +
+            " - Run with \"-help\" as first argument prints this message and exits.\n" +
+            " - Run with \"-doit\" runs the benchmark with summary details.\n" +
+            " - Run with \"-verbose\" provides additional details on the run.\n\n" +
+            "Example run :\n" +
+            "   java -Xms500m -Xmx500m -XX:NewSize=400m FormatMicroBenchmark -doit -verbose\n\n" +
+            "Note: \n" +
+            " - Vm options -Xms, -Xmx, -XX:NewSize must be set correctly for \n" +
+            "   getting reliable numbers. Otherwise GC activity may corrupt results.\n" +
+            "   As of jdk80b48 using \"-Xms500m -Xmx500m -XX:NewSize=400m\" covers \n" +
+            "   all cases.\n" +
+            " - Optionally using \"-XX:+printGC\" option provides information that \n" +
+            "   helps checking any GC activity while benches are run.\n\n" +
+            "Look at the heading comments and description in source code for " +
+            "detailed information.\n");
+    }
+
+    /* We will call stabilizeMemory before each call of benchFormat***().
+     * This in turn tries to clean up as much memory as possible.
+     * As a safe bound we limit number of System.gc() calls to 10,
+     * but most of the time two calls to System.gc() will be enough.
+     * If memory reporting is asked for, the method returns the difference
+     * of free memory between entering an leaving the method.
+     */
+    private static long stabilizeMemory(boolean reportConsumedMemory) {
+        final long oneMegabyte = 1024L * 1024L;
+
+        long refMemory = 0;
+        long initialMemoryLeft = Runtime.getRuntime().freeMemory();
+        long currMemoryLeft = initialMemoryLeft;
+        int nbGCCalls = 0;
+
+        do {
+            nbGCCalls++;
+
+            refMemory = currMemoryLeft;
+            System.gc();
+            currMemoryLeft = Runtime.getRuntime().freeMemory();
+
+        } while ((Math.abs(currMemoryLeft - refMemory) > oneMegabyte) &&
+                 (nbGCCalls < 10));
+
+        if (Verbose &&
+            reportConsumedMemory)
+            System.out.println("Memory consumed by previous run : " +
+                               (currMemoryLeft - initialMemoryLeft)/oneMegabyte + "Mbs.");
+
+        return currMemoryLeft;
+    }
+
+
+    // ---------- Integer only based bench --------------------
+    private static final String INTEGER_BENCH = "benchFormatInteger";
+    private static String benchFormatInteger(NumberFormat nf) {
+        String str = "";
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++)
+            str = nf.format((double) j);
+        return str;
+    }
+
+    // This reproduces the throughput load added in benchFormatInteger
+    static double integerThroughputLoad() {
+        double d = 0.0d;
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++) {
+            d = (double) j;
+        }
+        return d;
+    }
+
+    // Runs integerThroughputLoad and calculate its mean load
+    static void calculateIntegerThroughputLoad() {
+        int nbRuns = NB_RUNS;
+        long elapsedTime = 0;
+        double foo;
+
+        for (int i = 1; i <= nbRuns; i++) {
+
+            long startTime = System.nanoTime();
+            foo = integerThroughputLoad();
+            long estimatedTime = System.nanoTime() - startTime;
+            if (i > 3) elapsedTime += estimatedTime / 1000;
+        }
+
+
+        if (Verbose)
+            System.out.println(
+               "calculated throughput load for " + INTEGER_BENCH +
+               " bench is = " + (elapsedTime / (nbRuns - 3)) + " microseconds");
+    }
+
+    // ---------- Fractional only based bench --------------------
+    private static final String FRACTIONAL_BENCH = "benchFormatFractional";
+    private static String benchFormatFractional(NumberFormat nf) {
+        String str = "";
+        double floatingN = 1.0d / (double) MAX_RANGE;
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++)
+            str = nf.format(floatingN * (double) j);
+        return str;
+    }
+
+    // This reproduces the throughput load added in benchFormatFractional
+    static double fractionalThroughputLoad() {
+        double d = 0.0d;
+        double floatingN = 1.0d / (double) MAX_RANGE;
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++) {
+            d = floatingN * (double) j;
+        }
+        return d;
+    }
+
+    // Runs fractionalThroughputLoad and calculate its mean load
+    static void calculateFractionalThroughputLoad() {
+        int nbRuns = NB_RUNS;
+        long elapsedTime = 0;
+        double foo;
+
+        for (int i = 1; i <= nbRuns; i++) {
+
+            long startTime = System.nanoTime();
+            foo = fractionalThroughputLoad();
+            long estimatedTime = System.nanoTime() - startTime;
+            if (i > 3) elapsedTime += estimatedTime / 1000;
+        }
+
+        if (Verbose)
+        System.out.println(
+            "calculated throughput load for " + FRACTIONAL_BENCH +
+            " bench is = " + (elapsedTime / (nbRuns - 3)) + " microseconds");
+    }
+
+    // ---------- An Small Integral bench --------------------
+    //  that limits the magnitude of tested double values
+    private static final String SMALL_INTEGRAL_BENCH = "benchFormatSmallIntegral";
+    private static String benchFormatSmallIntegral(NumberFormat nf) {
+        String str = "";
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++)
+            str = nf.format(((double) j) / 1000.0d);
+        return str;
+    }
+
+    // This reproduces the throughput load added in benchFormatSmallIntegral
+    static double smallIntegralThroughputLoad() {
+        double d = 0.0d;
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++) {
+            d = (double) j / 1000.0d;
+        }
+        return d;
+    }
+
+    // Runs small_integralThroughputLoad and calculate its mean load
+    static void calculateSmallIntegralThroughputLoad() {
+        int nbRuns = NB_RUNS;
+        long elapsedTime = 0;
+        double foo;
+
+        for (int i = 1; i <= nbRuns; i++) {
+
+            long startTime = System.nanoTime();
+            foo = smallIntegralThroughputLoad();
+            long estimatedTime = System.nanoTime() - startTime;
+            if (i > 3) elapsedTime += estimatedTime / 1000;
+        }
+
+        if (Verbose)
+        System.out.println(
+            "calculated throughput load for " + SMALL_INTEGRAL_BENCH +
+            " bench is = " + (elapsedTime / (nbRuns - 3)) + " microseconds");
+    }
+
+    // ---------- A fair and simple bench --------------------
+    private static final String FAIR_SIMPLE_BENCH = "benchFormatFairSimple";
+    private static String benchFormatFairSimple(NumberFormat nf, boolean isCurrency) {
+        String str = "";
+        double seed = isCurrency ?  0.0010203040506070809 : 0.00010203040506070809;
+        double d = (double) -MAX_RANGE;
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++) {
+            d = d  + 1.0d + seed;
+            str = nf.format(d);
+        }
+        return str;
+    }
+
+    // This reproduces the throughput load added in benchFormatFairSimple
+    static double fairSimpleThroughputLoad() {
+        double seed =  0.00010203040506070809;
+        double delta = 0.0d;
+        double d = (double) -MAX_RANGE;
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++) {
+            d = d + 1.0d + seed;
+        }
+        return d;
+    }
+
+    // Runs fairThroughputLoad and calculate its mean load
+    static void calculateFairSimpleThroughputLoad() {
+        int nbRuns = NB_RUNS;
+        long elapsedTime = 0;
+        double foo;
+
+        for (int i = 1; i <= nbRuns; i++) {
+
+            long startTime = System.nanoTime();
+            foo = fairSimpleThroughputLoad();
+            long estimatedTime = System.nanoTime() - startTime;
+            if (i > 3) elapsedTime += estimatedTime / 1000;
+        }
+
+        if (Verbose)
+        System.out.println(
+            "calculated throughput load for " + FAIR_SIMPLE_BENCH +
+            " bench is = " + (elapsedTime / (nbRuns - 3)) + " microseconds");
+    }
+
+    // ---------- Fractional part is only made of nines bench --------------
+    private static final String FRACTIONAL_ALL_NINES_BENCH = "benchFormatFractionalAllNines";
+    private static String benchFormatFractionalAllNines(NumberFormat nf, boolean isCurrency) {
+        String str = "";
+        double fractionalEven = isCurrency ?  0.993000001 : 0.99930000001;
+        double fractionalOdd  = isCurrency ?  0.996000001 : 0.99960000001;
+        double fractional;
+        double d;
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++) {
+            if ((j & 1) == 0)
+                fractional = fractionalEven;
+            else
+                fractional = fractionalOdd;
+            if ( j >= 0)
+                d = (double ) j + fractional;
+            else d = (double) j - fractional;
+            str = nf.format(d);
+        }
+        return str;
+    }
+
+    // This reproduces the throughput load added in benchFormatFractionalAllNines
+    static double fractionalAllNinesThroughputLoad() {
+        double fractionalEven = 0.99930000001;
+        double fractionalOdd  = 0.99960000001;
+        double fractional;
+        double d = 0.0d;
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++) {
+            if ((j & 1) == 0)
+                fractional = fractionalEven;
+            else fractional = fractionalOdd;
+            if ( j >= 0)
+                d = (double ) j + fractional;
+            else d = (double) j - fractional;
+        }
+        return d;
+    }
+
+    // Runs fractionalAllNinesThroughputLoad and calculate its mean load
+    static void calculateFractionalAllNinesThroughputLoad() {
+        int nbRuns = NB_RUNS;
+        long elapsedTime = 0;
+        double foo;
+
+        for (int i = 1; i <= nbRuns; i++) {
+
+            long startTime = System.nanoTime();
+            foo = fractionalAllNinesThroughputLoad();
+            long estimatedTime = System.nanoTime() - startTime;
+            if (i > 3) elapsedTime += estimatedTime / 1000;
+        }
+
+        if (Verbose)
+            System.out.println(
+               "calculated throughput load for " + FRACTIONAL_ALL_NINES_BENCH +
+               " bench is = " + (elapsedTime / (nbRuns - 3)) + " microseconds");
+    }
+
+    // ---------- Number is only made of nines bench --------------
+    private static final String ALL_NINES_BENCH = "benchFormatAllNines";
+    private static String benchFormatAllNines(NumberFormat nf, boolean isCurrency) {
+        String str = "";
+        double[] decimaAllNines =
+            {9.9993, 99.9993, 999.9993, 9999.9993, 99999.9993,
+             999999.9993, 9999999.9993, 99999999.9993, 999999999.9993};
+        double[] currencyAllNines =
+            {9.993, 99.993, 999.993, 9999.993, 99999.993,
+             999999.993, 9999999.993, 99999999.993, 999999999.993};
+        double[] valuesArray = (isCurrency) ? currencyAllNines : decimaAllNines;
+        double seed = 1.0 / (double) MAX_RANGE;
+        double d;
+        int id;
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++) {
+            id = (j >=  0) ? j % 9 : -j % 9;
+            if ((j & 1) == 0)
+                d = valuesArray[id] + id * seed;
+            else
+                d = valuesArray[id] - id * seed;
+            str = nf.format(d);
+        }
+        return str;
+    }
+
+    // This reproduces the throughput load added in benchFormatAllNines
+    static double allNinesThroughputLoad() {
+        double[] decimaAllNines =
+            {9.9993, 99.9993, 999.9993, 9999.9993, 99999.9993,
+             999999.9993, 9999999.9993, 99999999.9993, 999999999.9993};
+        double[] valuesArray = decimaAllNines;
+        double seed = 1.0 / (double) MAX_RANGE;
+        double d = 0.0d;
+        int id;
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++) {
+            id = (j >=  0) ? j % 9 : -j % 9;
+            if ((j & 1) == 0)
+                d = valuesArray[id] + id * seed;
+            else
+                d = valuesArray[id] - id * seed;
+        }
+        return d;
+    }
+
+    // Runs allNinesThroughputLoad and calculate its mean load
+    static void calculateAllNinesThroughputLoad() {
+        int nbRuns = NB_RUNS;
+        long elapsedTime = 0;
+        double foo;
+
+        for (int i = 1; i <= nbRuns; i++) {
+
+            long startTime = System.nanoTime();
+            foo = allNinesThroughputLoad();
+            long estimatedTime = System.nanoTime() - startTime;
+            if (i > 3) elapsedTime += estimatedTime / 1000;
+        }
+
+        if (Verbose)
+            System.out.println(
+               "calculated throughput load for " + ALL_NINES_BENCH +
+               " bench is = " + (elapsedTime / (nbRuns - 3)) + " microseconds");
+    }
+
+
+
+    // --- A fair bench trying (hopefully) to reproduce business applicatons  ---
+
+    /*  benchFormatFair uses the following formula :
+     *   y = F(x) = sign(x) * x**2 * ((1000/MAX_RANGE)**2).
+     *
+     *  which converts in the loop as (if j is the loop index) :
+     *   x = double(j)
+     *   k = 1000.0d * double(MAX_RANGE)
+     *   y = sign(j) * x**2 * k**2
+     *
+     *  This is a flattened parabolic curve where only the j values
+     *  in [-1000, 1000] will provide y results in [-1, +1] interval,
+     *  and for abs(j) >= 1000 the result y will be greater than 1.
+     *
+     *  The difference with benchFormatSmallIntegral is that since y results
+     *  follow a parabolic curve the magnitude of y grows much more rapidly
+     *  and closer to j values when abs(j) >= 1000:
+     *   - for |j| < 1000,  SmallIntegral(j) < 1.0 and fair(j) < 1.0
+     *   - for j in [1000, 10000[
+     *      SmallIntegral(j) is in [1, 10[
+     *      Fair(j) is in [4, 400[
+     *   - for j in [10000,100000[
+     *      SmallIntegral(j) is in [10, 100[
+     *      Fair(j) is in [400,40000[
+     *   - for j in [100000,1000000[
+     *      SmallIntegral(j) is in [100, 1000[
+     *      Fair(j) is in [40000, 4000000[
+     *
+     *  Since double values for j less than 100000 provide only 4 digits in the
+     *  integral, values greater than 250000 provide at least 6 digits, and 500000
+     *  computes to 1000000, the distribution is roughly half with less than 5
+     *  digits and half with at least 6 digits in the integral part.
+     *
+     *  Compared to FairSimple bench, this represents an application where 20% of
+     *  the double values to format are less than 40000.0 absolute value.
+     *
+     *  Fair(j) is close to the magnitude of j when j > 100000 and is hopefully
+     *  more representative of what may be found in general in business apps.
+     *  (assumption : there will be mainly either small or large values, and
+     *   less values in middle range).
+     *
+     *  We could get even more precise distribution of values using formula :
+     *   y = sign(x) * abs(x)**n * ((1000 / MAX_RANGE)**n) where n > 2,
+     *  or even well-known statistics function to fine target such distribution,
+     *  but we have considred that the throughput load for calculating y would
+     *  then be too high. We thus restrain the use of a power of 2 formula.
+     */
+
+    private static final String FAIR_BENCH = "benchFormatFair";
+    private static String benchFormatFair(NumberFormat nf) {
+        String str = "";
+        double k = 1000.0d / (double) MAX_RANGE;
+        k *= k;
+
+        double d;
+        double absj;
+        double jPowerOf2;
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++) {
+            absj = (double) j;
+            jPowerOf2 = absj * absj;
+            d = k * jPowerOf2;
+            if (j < 0) d = -d;
+            str = nf.format(d);
+        }
+        return str;
+    }
+
+    // This is the exact throughput load added in benchFormatFair
+    static double fairThroughputLoad() {
+        double k = 1000.0d / (double) MAX_RANGE;
+        k *= k;
+
+        double d = 0.0d;
+        double absj;
+        double jPowerOf2;
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++) {
+            absj = (double) j;
+            jPowerOf2 = absj * absj;
+            d = k * jPowerOf2;
+            if (j < 0) d = -d;
+        }
+        return d;
+    }
+
+    // Runs fairThroughputLoad and calculate its mean load
+    static void calculateFairThroughputLoad() {
+        int nbRuns = NB_RUNS;
+        long elapsedTime = 0;
+        double foo;
+
+        for (int i = 1; i <= nbRuns; i++) {
+
+            long startTime = System.nanoTime();
+            foo = fairThroughputLoad();
+            long estimatedTime = System.nanoTime() - startTime;
+            if (i > 3) elapsedTime += estimatedTime / 1000;
+        }
+
+        if (Verbose)
+            System.out.println(
+               "calculated throughput load for " + FAIR_BENCH +
+               " bench is = " + (elapsedTime / (nbRuns - 3)) + " microseconds");
+    }
+
+    // ---------- All double values are very close to a tie --------------------
+    // i.e. like 123.1235 (for decimal case) or 123.125 (for currency case).
+
+    private static final String TIE_BENCH = "benchFormatTie";
+    private static String benchFormatTie(NumberFormat nf, boolean isCurrency) {
+        double d;
+        String str = "";
+        double fractionaScaling = (isCurrency) ? 1000.0d : 10000.0d;
+        int fixedFractionalPart = (isCurrency) ? 125 : 1235;
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++) {
+            d = (((double) j * fractionaScaling) +
+                 (double) fixedFractionalPart) / fractionaScaling;
+            str = nf.format(d);
+        }
+        return str;
+    }
+
+    // This is the exact throughput load added in benchFormatTie
+    static double tieThroughputLoad(boolean isCurrency) {
+        double d = 0.0d;
+        double fractionaScaling = (isCurrency) ? 1000.0d : 10000.0d;
+        int fixedFractionalPart = (isCurrency) ? 125 : 1235;
+        for (int j = - MAX_RANGE; j <= MAX_RANGE; j++) {
+            d = (((double) j * fractionaScaling) +
+                 (double) fixedFractionalPart) / fractionaScaling;
+        }
+        return d;
+    }
+
+    // Runs tieThroughputLoad and calculate its mean load
+    static void calculateTieThroughputLoad(boolean isCurrency) {
+        int nbRuns = NB_RUNS;
+        long elapsedTime = 0;
+        double foo;
+
+        for (int i = 1; i <= nbRuns; i++) {
+
+            long startTime = System.nanoTime();
+            foo = tieThroughputLoad(isCurrency);
+            long estimatedTime = System.nanoTime() - startTime;
+            if (i > 3) elapsedTime += estimatedTime / 1000;
+        }
+
+        if (Verbose)
+            System.out.println(
+               "calculated throughput load for " + TIE_BENCH +
+               " bench is = " + (elapsedTime / (nbRuns - 3)) + " microseconds");
+    }
+
+
+    // Print statistics for passed times results of benchName.
+    static void printPerfResults(long[] times, String benchName) {
+        int nbBenches = times.length;
+
+        long totalTimeSpent = 0;
+        long meanTimeSpent;
+
+        double variance = 0;
+        double standardDeviation = 0;
+
+        // Calculates mean spent time
+        for (int i = 1; i <= nbBenches; i++)
+            totalTimeSpent += times[i-1];
+        meanTimeSpent = totalTimeSpent / nbBenches;
+
+        // Calculates standard deviation
+        for (int j = 1; j <= nbBenches; j++)
+            variance += Math.pow(((double)times[j-1] - (double)meanTimeSpent), 2);
+        variance = variance / (double) times.length;
+        standardDeviation = Math.sqrt(variance) / meanTimeSpent;
+
+        // Print result and statistics for benchName
+        System.out.println(
+           "Statistics (starting at 4th bench) for bench " + benchName +
+           "\n for last " + nbBenches +
+           " runs out of " + NB_RUNS +
+           " , each with 2x" + MAX_RANGE + " format(double) calls : " +
+           "\n  mean exec time = " + meanTimeSpent + " microseconds" +
+           "\n  standard deviation = " + String.format("%.3f", standardDeviation) + "% \n");
+    }
+
+    public static void main(String[] args) {
+
+        if (args.length >= 1) {
+            // Parse args, just checks expected ones. Ignore others or dups.
+            if (args[0].equals("-help")) {
+                usage();
+                return;
+            }
+
+            for (String s : args) {
+                if (s.equals("-doit"))
+                    DoIt = true;
+                else if (s.equals("-verbose"))
+                    Verbose = true;
+            }
+        } else {
+            // No arguments, skips the benchmarks and exits.
+            System.out.println(
+                "Test skipped with success by default. See -help for details.");
+            return;
+        }
+
+        if (!DoIt) {
+            if (Verbose)
+                usage();
+            System.out.println(
+                "Test skipped and considered successful.");
+            return;
+        }
+
+        System.out.println("Single Threaded micro benchmark evaluating " +
+                           "the throughput of java.text.DecimalFormat.format() call stack.\n");
+
+        String fooString = "";
+
+        // Run benches for decimal instance
+        DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(Locale.US);
+        System.out.println("Running with a decimal instance of DecimalFormat.");
+
+        calculateIntegerThroughputLoad();
+        fooString =
+            BenchType.INTEGER_BENCH.runBenchAndPrintStatistics(NB_RUNS, df, false);
+
+        calculateFractionalThroughputLoad();
+        fooString =
+            BenchType.FRACTIONAL_BENCH.runBenchAndPrintStatistics(NB_RUNS, df, false);
+
+        calculateSmallIntegralThroughputLoad();
+        fooString =
+            BenchType.SMALL_INTEGRAL_BENCH.runBenchAndPrintStatistics(NB_RUNS, df, false);
+
+        calculateFractionalAllNinesThroughputLoad();
+        fooString =
+            BenchType.FRACTIONAL_ALL_NINES_BENCH.runBenchAndPrintStatistics(NB_RUNS, df, false);
+
+        calculateAllNinesThroughputLoad();
+        fooString =
+            BenchType.ALL_NINES_BENCH.runBenchAndPrintStatistics(NB_RUNS, df, false);
+
+        calculateFairSimpleThroughputLoad();
+        fooString =
+            BenchType.FAIR_SIMPLE_BENCH.runBenchAndPrintStatistics(NB_RUNS, df, false);
+
+        calculateFairThroughputLoad();
+        fooString =
+            BenchType.FAIR_BENCH.runBenchAndPrintStatistics(NB_RUNS, df, false);
+
+        calculateTieThroughputLoad(false);
+        fooString =
+            BenchType.TIE_BENCH.runBenchAndPrintStatistics(NB_RUNS, df, false);
+
+        // Run benches for currency instance
+        DecimalFormat cf = (DecimalFormat) NumberFormat.getCurrencyInstance(Locale.US);
+        System.out.println("Running with a currency instance of DecimalFormat.");
+
+        calculateIntegerThroughputLoad();
+        fooString =
+            BenchType.INTEGER_BENCH.runBenchAndPrintStatistics(NB_RUNS, cf, false);
+
+        calculateFractionalThroughputLoad();
+        fooString =
+            BenchType.FRACTIONAL_BENCH.runBenchAndPrintStatistics(NB_RUNS, cf, false);
+
+        calculateSmallIntegralThroughputLoad();
+        fooString =
+            BenchType.SMALL_INTEGRAL_BENCH.runBenchAndPrintStatistics(NB_RUNS, cf, false);
+
+        calculateFractionalAllNinesThroughputLoad();
+        fooString =
+            BenchType.FRACTIONAL_ALL_NINES_BENCH.runBenchAndPrintStatistics(NB_RUNS, cf, false);
+
+        calculateAllNinesThroughputLoad();
+        fooString =
+            BenchType.ALL_NINES_BENCH.runBenchAndPrintStatistics(NB_RUNS, cf, false);
+
+        calculateFairSimpleThroughputLoad();
+        fooString =
+            BenchType.FAIR_SIMPLE_BENCH.runBenchAndPrintStatistics(NB_RUNS, cf, false);
+
+        calculateFairThroughputLoad();
+        fooString =
+            BenchType.FAIR_BENCH.runBenchAndPrintStatistics(NB_RUNS, cf, false);
+
+        calculateTieThroughputLoad(false);
+        fooString =
+            BenchType.TIE_BENCH.runBenchAndPrintStatistics(NB_RUNS, cf, false);
+
+    }
+
+    // This class to factorise what would be duplicated otherwise.
+    static enum BenchType {
+
+        INTEGER_BENCH("benchFormatInteger"),
+        FRACTIONAL_BENCH("benchFormatFractional"),
+        SMALL_INTEGRAL_BENCH("benchFormatSmallIntegral"),
+        FAIR_SIMPLE_BENCH("benchFormatFairSimple"),
+        FRACTIONAL_ALL_NINES_BENCH("benchFormatFractionalAllNines"),
+        ALL_NINES_BENCH("benchFormatAllNines"),
+        FAIR_BENCH("benchFormatFair"),
+        TIE_BENCH("benchFormatTie");
+
+        private final String name;
+
+        BenchType(String name) {
+            this.name = name;
+        }
+
+        String runBenchAndPrintStatistics(int nbRuns,
+                         NumberFormat nf,
+                         boolean isCurrency) {
+
+            // We eliminate the first 3 runs in the time measurements
+            // to let C2 do complete compilation and optimization work.
+            long[] elapsedTimes = new long[nbRuns - 3];
+
+            System.out.println("Now running " + nbRuns + " times bench " + name);
+
+            String str = "";
+            for (int i = 1; i <= nbRuns; i++) {
+
+                stabilizeMemory(false);
+                long startTime = System.nanoTime();
+
+                switch(this) {
+                case INTEGER_BENCH :
+                    str = benchFormatInteger(nf);
+                    break;
+                case FRACTIONAL_BENCH :
+                    str = benchFormatFractional(nf);
+                    break;
+                case SMALL_INTEGRAL_BENCH :
+                    str = benchFormatSmallIntegral(nf);
+                    break;
+                case FRACTIONAL_ALL_NINES_BENCH :
+                    str = benchFormatFractionalAllNines(nf, isCurrency);
+                    break;
+                case ALL_NINES_BENCH :
+                    str = benchFormatAllNines(nf, isCurrency);
+                    break;
+                case FAIR_SIMPLE_BENCH :
+                    str = benchFormatFairSimple(nf, isCurrency);
+                    break;
+                case FAIR_BENCH :
+                    str = benchFormatFair(nf);
+                    break;
+                case TIE_BENCH :
+                    str = benchFormatTie(nf, isCurrency);
+                    break;
+
+                default:
+                }
+
+
+                long estimatedTime = System.nanoTime() - startTime;
+                if (i > 3)
+                    elapsedTimes[i-4] = estimatedTime / 1000;
+
+                if (Verbose)
+                    System.out.println(
+                                       "calculated time for " + name +
+                                       " bench " + i + " is = " +
+                                       (estimatedTime / 1000) + " microseconds");
+                else System.out.print(".");
+
+                stabilizeMemory(true);
+            }
+
+            System.out.println(name + " Done.");
+
+            printPerfResults(elapsedTimes, name);
+
+            return str;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DecimalFormat/GoldenDoubleValues.java	Tue Oct 02 10:11:57 2012 +0100
@@ -0,0 +1,965 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* Set of constants and values used in RoundingAndPropertyTest.java.
+ *
+ * There are 5 different information in this class:
+ * - TestLocale is the locale used by RoundingAndPropertyTest regression test
+ *   when calling DecimalFormat.format() on either the set of DecimalGoldenValues
+ *   or CurrencyGoldenValues.
+ *   See main method of RoundingAndPropertyTest.
+ *
+ * - FullLocalizationTestLocale is the locale used by RoundingAndPropertyTest
+ *   regression test when calling DecimalFormat.format() on the set of values
+ *   (DecimalLocalizationValues) used to test that localization of digits
+ *   happens correctly when needed.
+ *   See main method of RoundingAndPropertyTest.
+ *
+ * - DecimalLocalizationValues is an array containing all the double values used
+ *   to check that localization of digits happens correctly when needed.
+ *   See RoundingAndPropertyTest.testLocalizationValues() method.
+ *
+ * - DecimalGoldenValues and CurrencyGoldenValues are arrays containing all the
+ *   double values that will be used as input when checking correctness of
+ *   results returned by DecimalFormat.format().
+ *   2 arrays are needed since decimal and currency formatting patterns require
+ *   a different number of digits after decimal point.
+ *   See RoundingAndPropertyTest.testGoldenValues() method.
+ *
+ * - PROPERTY_CHECK_POSITIVE_VALUE and PROPERTY_CHECK_NEGATIVE_VALUE are the
+ *   double values used for testing the validity of the property changes call
+ *   in the fast-path case. The locale used in that case is TestLocale.
+ *   See RoundingAndPropertyTest.testSettersAndFastPath() method.
+ */
+
+import java.util.*;
+
+class GoldenDoubleValues {
+
+    // TestLocale is the testing locale used by RoundingAndPropertyTest test,
+    // when testing the golden double values
+    static final Locale TestLocale = new Locale("en", "US");
+
+
+    // FullTestLocale is the testing locale used by RoundingAndPropertyTest test,
+    // when testing full localization of double values.
+    static final Locale FullLocalizationTestLocale = new Locale("hi", "IN");
+
+
+    /* Below are the two double values used for exercising the changes of
+     * of DecimalFormat properties and symbols. These values are also used
+     * as golden values (see golden arrays below).
+     */
+
+    /* PROPERTY_CHECK_NEGATIVE_VALUE is the negative double value used for
+     * testing the validity of the property changes for fast-path.
+     * See testSettersAndFastPath() in RoundingAndPropertyTest test.
+     */
+    static final double PROPERTY_CHECK_NEGATIVE_VALUE = -2147483646.2334997d;
+
+    /* PROPERTY_CHECK_POSITIVE_VALUE is the positive double value used for
+     * testing the validity of the property changes for fast-path.
+     * See testSettersAndFastPath() in RoundingAndPropertyTest test.
+     */
+    static final double PROPERTY_CHECK_POSITIVE_VALUE =  2147483646.2335003d;
+
+    /* --- Array of double values to test localization ------------------------
+     *
+     * For most locales, effective localization does not happen on digits, i.e.
+     * the digits are not changed due to localization. In order to check that
+     * fast-path localize correctly digits in such a case, the array of double
+     * values below deals with all the case of localization that may happen on
+     * digits
+     */
+    static final double[] DecimalLocalizationValues = {
+        1.123,
+        12.123,
+        123.123,
+        1234.123,
+        12345.123,
+        123456.123,
+        1234567.123,
+        12345678.123,
+        123456789.123,
+        1234567890.123,
+        1234.0,
+        1234.9,
+        1234.99,
+        1234.999
+    };
+
+
+    /* --- Arrays of golden double values ----------------------------------
+     *
+     * The   GoldenValues arrays  are used   as input values   for checking the
+     * correctness  of  the    DecimalFormat.format()  call  results  done   in
+     * RoundingAndPropertyTest regression test. The results are compared to the
+     * expected ones  found in  GoldenFormattedValues.  For each value   in the
+     * arrays  there  is   a corresponding    expected  string  result   found,
+     * represented as an array  of unicode values, at  the same index  in the
+     * related GoldenFormattedValues array.  The string returned by  the format
+     * call and the found in GoldenFormattedValues array  must be equal for the
+     * result to be considered valid.
+     * See RoundingAndPropertyTest.testGoldenValues() method.
+     *
+     * We  need 2  such  GoldenValues  arrays  since the decimal  and  currency
+     * formatting rules require different number of digits after decimal point.
+     *
+     * Thus we have two different arrays of golden values:
+     *  - DecimalGoldenValues for the decimal case.
+     *  - CurrencyGoldenValues for the currency case.
+     *
+     * They are associated to related GoldenFormattedValues arrays, generated by
+     * running RoundingAndPropertyTest with a "gengold" argument:
+     *  - DecimalGoldenFormattedValues for the decimal case.
+     *  - CurrencyGoldenFormattedValues for the currency case.
+     * These two generated arrays are found in GoldenFormattedValues.java file.
+     *
+     * The  impact of the formatting rules  is as follows,  because the pattern
+     * rule for  the  fractional  part is different   for  decimal and currency
+     * patterns:
+     *  - in decimal case one must output the first non-zero 3 digits of
+     *    fractional part 1.1232 => "1.123" and 1.12016789 => "1.12"
+     *  - in currency case the first 2 fractional digits are always output
+     *    1.1232 => "1.12" and 1.0016789 => "1.00"
+     *
+     * Thus we  need a different  number of  fractional digits when  we specify
+     * below the golden double values to check, and most of the decimal and
+     * currency golden values differ only in the number of fractional digits.
+     *
+     * The list below exercises almost all code pathes of the fast-path
+     * algorithm except localization of digits.
+     */
+
+    // --- The set of golden values for the Decimal formatting case --------
+    static final double[] DecimalGoldenValues = {
+        // Testing of specific values
+        +0.0,
+        -0.0,
+        Double.MIN_VALUE,
+        Double.MIN_NORMAL,
+        PROPERTY_CHECK_NEGATIVE_VALUE,
+        PROPERTY_CHECK_POSITIVE_VALUE,
+        -2147483647.9996,
+        2147483647.9996,
+        -1999999999.9994997,
+        1999999999.9995003,
+        // Testing fast-path range checks (all outside bounds)
+        Double.NaN,
+        Double.POSITIVE_INFINITY,
+        Double.NEGATIVE_INFINITY,
+        Double.MAX_VALUE,
+        -9876543210.9876543,
+        9876543210.9876543,
+        -1234567890.1234567E128,
+        1234567890.1234567E128,
+        // Testing of integral string size
+        1.123,
+        12.123,
+        123.123,
+        1234.123,
+        12345.123,
+        123456.123,
+        1234567.123,
+        12345678.123,
+        123456789.123,
+        1234567890.123,
+        -1.123,
+        -12.123,
+        -123.123,
+        -1234.123,
+        -12345.123,
+        -123456.123,
+        -1234567.123,
+        -12345678.123,
+        -123456789.123,
+        -1234567890.123,
+        // Testing of fractional string size
+        0.1,
+        0.12,
+        0.123,
+        0.1234,
+        10.1,
+        10.12,
+        10.123,
+        10.1234,
+        100.1,
+        100.12,
+        100.123,
+        100.1234,
+        1000.1,
+        1000.12,
+        1000.123,
+        1000.1234,
+        10000.1,
+        10000.12,
+        10000.123,
+        10000.1234,
+        100000.1,
+        100000.12,
+        100000.123,
+        100000.1234,
+        1000000.1,
+        1000000.12,
+        1000000.123,
+        1000000.1234,
+        10000000.1,
+        10000000.12,
+        10000000.123,
+        10000000.1234,
+        100000000.1,
+        100000000.12,
+        100000000.123,
+        100000000.1234,
+        1000000000.1,
+        1000000000.12,
+        1000000000.123,
+        1000000000.1234,
+        -0.1,
+        -0.12,
+        -0.123,
+        -0.1234,
+        -10.1,
+        -10.12,
+        -10.123,
+        -10.1234,
+        -100.1,
+        -100.12,
+        -100.123,
+        -100.1234,
+        -1000.1,
+        -1000.12,
+        -1000.123,
+        -1000.1234,
+        -10000.1,
+        -10000.12,
+        -10000.123,
+        -10000.1234,
+        -100000.1,
+        -100000.12,
+        -100000.123,
+        -100000.1234,
+        -1000000.1,
+        -1000000.12,
+        -1000000.123,
+        -1000000.1234,
+        -10000000.1,
+        -10000000.12,
+        -10000000.123,
+        -10000000.1234,
+        -100000000.1,
+        -100000000.12,
+        -100000000.123,
+        -100000000.1234,
+        -1000000000.1,
+        -1000000000.12,
+        -1000000000.123,
+        -1000000000.1234,
+        // Testing of special rounding cases
+        1.9993,
+        12.9993,
+        123.9993,
+        1234.9993,
+        12345.9993,
+        123456.9993,
+        1234567.9993,
+        12345678.9993,
+        123456789.9993,
+        1234567890.9993,
+        1.9996,
+        12.9996,
+        123.9996,
+        1234.9996,
+        12345.9996,
+        123456.9996,
+        1234567.9996,
+        12345678.9996,
+        123456789.9996,
+        1234567890.9996,
+        -1.9993,
+        -12.9993,
+        -123.9993,
+        -1234.9993,
+        -12345.9993,
+        -123456.9993,
+        -1234567.9993,
+        -12345678.9993,
+        -123456789.9993,
+        -1234567890.9993,
+        -1.9996,
+        -12.9996,
+        -123.9996,
+        -1234.9996,
+        -12345.9996,
+        -123456.9996,
+        -1234567.9996,
+        -12345678.9996,
+        -123456789.9996,
+        -1234567890.9996,
+        109.9996,
+        1099.9996,
+        10999.9996,
+        109999.9996,
+        1099999.9996,
+        10999999.9996,
+        109999999.9996,
+        1099999999.9996,
+        -109.9996,
+        -1099.9996,
+        -10999.9996,
+        -109999.9996,
+        -1099999.9996,
+        -10999999.9996,
+        -109999999.9996,
+        -1099999999.9996,
+        1.9996,
+        19.9996,
+        199.9996,
+        1999.9996,
+        19999.9996,
+        199999.9996,
+        1999999.9996,
+        19999999.9996,
+        199999999.9996,
+        1999999999.9996,
+        -1.9996,
+        -19.9996,
+        -199.9996,
+        -1999.9996,
+        -19999.9996,
+        -199999.9996,
+        -1999999.9996,
+        -19999999.9996,
+        -199999999.9996,
+        -1999999999.9996,
+        // Testing for all nines cases
+        9.9996,
+        99.9996,
+        999.9996,
+        9999.9996,
+        99999.9996,
+        999999.9996,
+        9999999.9996,
+        99999999.9996,
+        999999999.9996,
+        9.999,
+        99.999,
+        999.999,
+        9999.999,
+        99999.999,
+        999999.999,
+        9999999.999,
+        99999999.999,
+        999999999.999,
+        -9.9996,
+        -99.9996,
+        -999.9996,
+        -9999.9996,
+        -99999.9996,
+        -999999.9996,
+        -9999999.9996,
+        -99999999.9996,
+        -999999999.9996,
+        -9.999,
+        -99.999,
+        -999.999,
+        -9999.999,
+        -99999.999,
+        -999999.999,
+        -9999999.999,
+        -99999999.999,
+        -999999999.999,
+        // Testing for no Fractional part cases
+        1.0,
+        12.0,
+        123.0,
+        1234.0,
+        12345.0,
+        123456.0,
+        1234567.0,
+        12345678.0,
+        123456789.0,
+        1234567890.0,
+        -1.0,
+        -12.0,
+        -123.0,
+        -1234.0,
+        -12345.0,
+        -123456.0,
+        -1234567.0,
+        -12345678.0,
+        -123456789.0,
+        -1234567890.0,
+        // Testing of tricky cases
+        -2599.399999990123,
+        -2599.339999990123,
+        -2599.333999990123,
+        1.000099999999818,
+        1.000199999999818,
+        1.000299999999818,
+        1.000399999999818,
+        1.000499999999818,
+        1.000599999999818,
+        1.000699999999818,
+        1.000799999999818,
+        1.000899999999818,
+        1.000999999999818,
+        1.2224999999999980,
+        1.2224999999999981,
+        1.2224999999999982,
+        1.2224999999999983,
+        1.2224999999999984,
+        1.2224999999999985,
+        1.2224999999999986,
+        1.2224999999999987,
+        1.2224999999999988,
+        1.2224999999999989,
+        1.2224999999999990,
+        1.2224999999999991,
+        1.2224999999999992,
+        1.2224999999999993,
+        1.2224999999999994,
+        1.2224999999999995,
+        1.2224999999999996,
+        1.2224999999999997,
+        1.2224999999999998,
+        // 1.2225 and 1.2224999999999999 have the same double approximation
+        1.2225,
+        1.2225000000000001,
+        1.2225000000000002,
+        1.2225000000000003,
+        1.2225000000000004,
+        1.2225000000000005,
+        1.2225000000000006,
+        1.2225000000000007,
+        1.2225000000000008,
+        1.2225000000000009,
+        1.2225000000000010,
+        1.2225000000000011,
+        1.2225000000000012,
+        1.2225000000000013,
+        1.2225000000000014,
+        1.2225000000000015,
+        1.2225000000000016,
+        1.2225000000000017,
+        1.2225000000000018,
+        1.2225000000000019,
+        // Tricky rounding cases around tie values
+        100913.67050000005,
+        199999.99895901306,
+        251846.3465,
+        253243.8825000001,
+        365045.85349999997,
+        314734.9615,
+        541133.9755,
+        858372.1225,
+        1000999.9995000001,
+        1347505.7825,
+        3358844.1975,
+        9997979.4085,
+        9993743.1585,
+        9938671.9085,
+        3385302.5465,
+        3404642.6605,
+        3431280.0865,
+        3438756.4754999997,
+        3446053.7874999996,
+        3457917.5125,
+        3465393.9014999997,
+        3484734.0154999997,
+        3492031.3274999997,
+        3503895.0525,
+        3511371.4414999997,
+        3518668.7534999996,
+        3530532.4785,
+        3538008.8674999997,
+        3545306.1794999996,
+        3557169.9045,
+        3557348.9814999998,
+        3564646.2934999997,
+        3583986.4074999997,
+        3591283.7194999997,
+        3603147.4445,
+        3610623.8334999997,
+        3617921.1454999996,
+        3629784.8705,
+        3637261.2594999997,
+        3656422.2965,
+        3656601.3734999998,
+        3663898.6854999997,
+        3675762.4105,
+        3683238.7994999997,
+        3690536.1114999996,
+        3702399.8365,
+        3709876.2254999997,
+        3717173.5374999996,
+        3729037.2625,
+        3736513.6514999997,
+        3755853.7654999997,
+        3763151.0774999997,
+        3775014.8025,
+        3782491.1914999997,
+        3789788.5034999996,
+        3801652.2285,
+        3809128.6174999997,
+        3816425.9294999996,
+        3828289.6545,
+        3828468.7314999998,
+        3835766.0434999997,
+        3855106.1574999997,
+        3862403.4694999997,
+        3874267.1945,
+        3881743.5834999997,
+        3889040.8954999996,
+        3900904.6205,
+        3908381.0094999997,
+        3927542.0465,
+        3927721.1234999998,
+        3935018.4354999997,
+        3946882.1605,
+        3954358.5494999997,
+        3961655.8614999996,
+        3973519.5865,
+        3980995.9754999997,
+        3988293.2874999996,
+        4000157.0125,
+        4007633.4014999997,
+        4026973.5154999997,
+        4034270.8274999997,
+        4046134.5525,
+        4053610.9414999997,
+        4060908.2534999996,
+        4072771.9785,
+        4080248.3674999997,
+        4087545.6794999996,
+        4099409.4045,
+        4099588.4814999998,
+        4106885.7934999997,
+        4126225.9074999997,
+        4133523.2194999997,
+        4145386.9445,
+        4152863.3334999997,
+        4160160.6454999996,
+        4172024.3705,
+        4179500.7594999997,
+        4198661.7965,
+        4203407.2865,
+        4210704.5985,
+        4213435.4975
+    };
+
+    // --- The set of golden values for the currency formatting case --------
+    static final double[] CurrencyGoldenValues = {
+        // Testing of specific values
+        +0.0,
+        -0.0,
+        Double.MIN_VALUE,
+        Double.MIN_NORMAL,
+        PROPERTY_CHECK_NEGATIVE_VALUE,
+        PROPERTY_CHECK_POSITIVE_VALUE,
+        -2147483647.996,
+        2147483647.996,
+        -1999999999.9949997,
+        1999999999.9950003,
+        // Testing fast-path range checks (all outside bounds)
+        Double.NaN,
+        Double.POSITIVE_INFINITY,
+        Double.NEGATIVE_INFINITY,
+        Double.MAX_VALUE,
+        -9876543210.9876543,
+        9876543210.9876543,
+        -1234567890.1234567E128,
+        1234567890.1234567E128,
+        // Testing of integral string size
+        1.12,
+        12.12,
+        123.12,
+        1234.12,
+        12345.12,
+        123456.12,
+        1234567.12,
+        12345678.12,
+        123456789.12,
+        1234567890.12,
+        -1.12,
+        -12.12,
+        -123.12,
+        -1234.12,
+        -12345.12,
+        -123456.12,
+        -1234567.12,
+        -12345678.12,
+        -123456789.12,
+        -1234567890.12,
+        // Testing of fractional string size
+        0.1,
+        0.12,
+        0.123,
+        10.1,
+        10.12,
+        10.123,
+        100.1,
+        100.12,
+        100.123,
+        1000.1,
+        1000.12,
+        1000.123,
+        10000.1,
+        10000.12,
+        10000.123,
+        100000.1,
+        100000.12,
+        100000.123,
+        1000000.1,
+        1000000.12,
+        1000000.123,
+        10000000.1,
+        10000000.12,
+        10000000.123,
+        100000000.1,
+        100000000.12,
+        100000000.123,
+        1000000000.1,
+        1000000000.12,
+        1000000000.123,
+        -0.1,
+        -0.12,
+        -0.123,
+        -10.1,
+        -10.12,
+        -10.123,
+        -100.1,
+        -100.12,
+        -100.123,
+        -1000.1,
+        -1000.12,
+        -1000.123,
+        -10000.1,
+        -10000.12,
+        -10000.123,
+        -100000.1,
+        -100000.12,
+        -100000.123,
+        -1000000.1,
+        -1000000.12,
+        -1000000.123,
+        -10000000.1,
+        -10000000.12,
+        -10000000.123,
+        -100000000.1,
+        -100000000.12,
+        -100000000.123,
+        -1000000000.1,
+        -1000000000.12,
+        -1000000000.123,
+        // Testing of special rounding cases
+        1.993,
+        12.993,
+        123.993,
+        1234.993,
+        12345.993,
+        123456.993,
+        1234567.993,
+        12345678.993,
+        123456789.993,
+        1234567890.993,
+        1.996,
+        12.996,
+        123.996,
+        1234.996,
+        12345.996,
+        123456.996,
+        1234567.996,
+        12345678.996,
+        123456789.996,
+        1234567890.996,
+        -1.993,
+        -12.993,
+        -123.993,
+        -1234.993,
+        -12345.993,
+        -123456.993,
+        -1234567.993,
+        -12345678.993,
+        -123456789.993,
+        -1234567890.993,
+        -1.996,
+        -12.996,
+        -123.996,
+        -1234.996,
+        -12345.996,
+        -123456.996,
+        -1234567.996,
+        -12345678.996,
+        -123456789.996,
+        -1234567890.996,
+        109.996,
+        1099.996,
+        10999.996,
+        109999.996,
+        1099999.996,
+        10999999.996,
+        109999999.996,
+        1099999999.996,
+        -109.996,
+        -1099.996,
+        -10999.996,
+        -109999.996,
+        -1099999.996,
+        -10999999.996,
+        -109999999.996,
+        -1099999999.996,
+        1.996,
+        19.996,
+        199.996,
+        1999.996,
+        19999.996,
+        199999.996,
+        1999999.996,
+        19999999.996,
+        199999999.996,
+        1999999999.996,
+        -1.996,
+        -19.996,
+        -199.996,
+        -1999.996,
+        -19999.996,
+        -199999.996,
+        -1999999.996,
+        -19999999.996,
+        -199999999.996,
+        -1999999999.996,
+        // Testing of all nines cases
+        9.996,
+        99.996,
+        999.996,
+        9999.996,
+        99999.996,
+        999999.996,
+        9999999.996,
+        99999999.996,
+        999999999.996,
+        9.99,
+        99.99,
+        999.99,
+        9999.99,
+        99999.99,
+        999999.99,
+        9999999.99,
+        99999999.99,
+        999999999.99,
+        -9.996,
+        -99.996,
+        -999.996,
+        -9999.996,
+        -99999.996,
+        -999999.996,
+        -9999999.996,
+        -99999999.996,
+        -999999999.996,
+        -9.99,
+        -99.99,
+        -999.99,
+        -9999.99,
+        -99999.99,
+        -999999.99,
+        -9999999.99,
+        -99999999.99,
+        -999999999.99,
+        // Testing of no Fractional part cases
+        1.0,
+        12.0,
+        123.0,
+        1234.0,
+        12345.0,
+        123456.0,
+        1234567.0,
+        12345678.0,
+        123456789.0,
+        1234567890.0,
+        -1.0,
+        -12.0,
+        -123.0,
+        -1234.0,
+        -12345.0,
+        -123456.0,
+        -1234567.0,
+        -12345678.0,
+        -123456789.0,
+        -1234567890.0,
+        // Testing of tricky cases
+        -2599.399999990123,
+        -2599.339999990123,
+        -2599.333999990123,
+        1.000999999999818,
+        1.001999999999818,
+        1.002999999999818,
+        1.003999999999818,
+        1.004999999999818,
+        1.005999999999818,
+        1.006999999999818,
+        1.007999999999818,
+        1.008999999999818,
+        1.009999999999818,
+        1.224999999999980,
+        1.224999999999981,
+        1.224999999999982,
+        1.224999999999983,
+        1.224999999999984,
+        1.224999999999985,
+        1.224999999999986,
+        1.224999999999987,
+        1.224999999999988,
+        1.224999999999989,
+        1.224999999999990,
+        1.224999999999991,
+        1.224999999999992,
+        1.224999999999993,
+        1.224999999999994,
+        1.224999999999995,
+        1.224999999999996,
+        1.224999999999997,
+        1.224999999999998,
+        1.224999999999999,
+        1.225,
+        1.225000000000001,
+        1.225000000000002,
+        1.225000000000003,
+        1.225000000000004,
+        1.225000000000005,
+        1.225000000000006,
+        1.225000000000007,
+        1.225000000000008,
+        1.225000000000009,
+        1.225000000000010,
+        1.225000000000011,
+        1.225000000000012,
+        1.225000000000013,
+        1.225000000000014,
+        1.225000000000015,
+        1.225000000000016,
+        1.225000000000017,
+        1.225000000000018,
+        1.225000000000019,
+        // Tricky rounding cases around tie values
+        1009136.7050000005,
+        2518463.465,
+        2532438.825000001,
+        3650458.5349999997,
+        3147349.615,
+        5411339.755,
+        8583721.225,
+        13475057.825,
+        33588441.975,
+        99979794.085,
+        99937431.585,
+        99386719.085,
+        33853025.465,
+        34046426.605,
+        34312800.865,
+        34387564.754999997,
+        34460537.874999996,
+        34579175.125,
+        34653939.014999997,
+        34847340.154999997,
+        34920313.274999997,
+        35038950.525,
+        35113714.414999997,
+        35186687.534999996,
+        35305324.785,
+        35380088.674999997,
+        35453061.794999996,
+        35571699.045,
+        35573489.814999998,
+        35646462.934999997,
+        35839864.074999997,
+        35912837.194999997,
+        36031474.445,
+        36106238.334999997,
+        36179211.454999996,
+        36297848.705,
+        36372612.594999997,
+        36564222.965,
+        36566013.734999998,
+        36638986.854999997,
+        36757624.105,
+        36832387.994999997,
+        36905361.114999996,
+        37023998.365,
+        37098762.254999997,
+        37171735.374999996,
+        37290372.625,
+        37365136.514999997,
+        37558537.654999997,
+        37631510.774999997,
+        37750148.025,
+        37824911.914999997,
+        37897885.034999996,
+        38016522.285,
+        38091286.174999997,
+        38164259.294999996,
+        38282896.545,
+        38284687.314999998,
+        38357660.434999997,
+        38551061.574999997,
+        38624034.694999997,
+        38742671.945,
+        38817435.834999997,
+        38890408.954999996,
+        39009046.205,
+        39083810.094999997,
+        39275420.465,
+        39277211.234999998,
+        39350184.354999997,
+        39468821.605,
+        39543585.494999997,
+        39616558.614999996,
+        39735195.865,
+        39809959.754999997,
+        39882932.874999996,
+        40001570.125,
+        40076334.014999997,
+        40269735.154999997,
+        40342708.274999997,
+        40461345.525,
+        40536109.414999997,
+        40609082.534999996,
+        40727719.785,
+        40802483.674999997,
+        40875456.794999996,
+        40994094.045,
+        40995884.814999998,
+        41068857.934999997,
+        41262259.074999997,
+        41335232.194999997,
+        41453869.445,
+        41528633.334999997,
+        41601606.454999996,
+        41720243.705,
+        41795007.594999997,
+        41986617.965,
+        42034072.865,
+        42107045.985,
+        42134354.975
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DecimalFormat/GoldenFormattedValues.java	Tue Oct 02 10:11:57 2012 +0100
@@ -0,0 +1,868 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* This is a machine generated file - Please DO NOT EDIT !
+ * Change RoundingAndPropertyTest instead,
+ * and run with "-gengold" argument to regenerate (without copyright header).
+ */
+
+/* This file contains the set of result Strings expected from calling inside
+ * RoundingAndPropertyTest the method NumberFormat.format() upon the set of
+ * double values provided in GoldenDoubleValues.java. It contains three arrays,
+ * each containing arrays of unicode values representing the expected string
+ * result when calling format() on the corresponding (i.e. same index) double
+ * value found in GoldenDoubleValues arrays :
+ * - DecimalDigitsLocalizedFormattedValues corresponds to DecimalLocalizationValues,
+ *   when using FullLocalizationTestLocale to format.
+ * - DecimalGoldenFormattedValues corresponds to DecimalGoldenValues, when used
+ *   in the decimal pattern case together with TestLocale.
+ * - CurrencyGoldenFormattedValues corresponds to CurrencyGoldenValues. when used
+ *   in the currency pattern case together with TestLocale.
+ * Please see documentation in RoundingAndPropertyTest.java for more details.
+ *
+ * This file generated by running RoundingAndPropertyTest with "-gengold" argument.
+ */
+
+class GoldenFormattedValues {
+
+    // The formatted values below were generated from golden values
+    // listed in GoldenDoubleValues.java, using the following jvm version :
+    //   Oracle Corporation Java HotSpot(TM) Server VM 1.8.0-ea
+    //   locale for golden double values : en_US
+    //   locale for testing digit localization : hi_IN
+
+    // The array of int[] unicode values storing the expected results
+    // when experiencing full localization of digits on DecimalLocalizationValues.
+    static int[][] DecimalDigitsLocalizedFormattedValues = {
+        { 2407, 46, 2407, 2408, 2409 },
+        { 2407, 2408, 46, 2407, 2408, 2409 },
+        { 2407, 2408, 2409, 46, 2407, 2408, 2409 },
+        { 2407, 44, 2408, 2409, 2410, 46, 2407, 2408, 2409 },
+        { 2407, 2408, 44, 2409, 2410, 2411, 46, 2407, 2408, 2409 },
+        { 2407, 2408, 2409, 44, 2410, 2411, 2412, 46, 2407, 2408, 2409 },
+        { 2407, 44, 2408, 2409, 2410, 44, 2411, 2412, 2413, 46, 2407, 2408, 2409 },
+        { 2407, 2408, 44, 2409, 2410, 2411, 44, 2412, 2413, 2414, 46, 2407, 2408, 2409 },
+        { 2407, 2408, 2409, 44, 2410, 2411, 2412, 44, 2413, 2414, 2415, 46, 2407, 2408, 2409 },
+        { 2407, 44, 2408, 2409, 2410, 44, 2411, 2412, 2413, 44, 2414, 2415, 2406, 46, 2407, 2408, 2409 },
+        { 2407, 44, 2408, 2409, 2410 },
+        { 2407, 44, 2408, 2409, 2410, 46, 2415 },
+        { 2407, 44, 2408, 2409, 2410, 46, 2415, 2415 },
+        { 2407, 44, 2408, 2409, 2410, 46, 2415, 2415, 2415 },
+    };
+
+    // The array of int[] unicode values storing the expected results
+    // when calling Decimal.format(double) on the decimal GoldenDoubleValues.
+    static int[][] DecimalGoldenFormattedValues = {
+        { 48 },
+        { 45, 48 },
+        { 48 },
+        { 48 },
+        { 45, 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 54, 46, 50, 51, 51 },
+        { 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 54, 46, 50, 51, 52 },
+        { 45, 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 56 },
+        { 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 56 },
+        { 45, 49, 44, 57, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 },
+        { 50, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 65533 },
+        { 8734 },
+        { 45, 8734 },
+        { 49, 55, 57, 44, 55, 54, 57, 44, 51, 49, 51, 44, 52, 56, 54, 44, 50, 51, 49, 44, 53, 55, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 45, 57, 44, 56, 55, 54, 44, 53, 52, 51, 44, 50, 49, 48, 46, 57, 56, 56 },
+        { 57, 44, 56, 55, 54, 44, 53, 52, 51, 44, 50, 49, 48, 46, 57, 56, 56 },
+        { 45, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 44, 48, 49, 50, 44, 51, 52, 53, 44, 54, 55, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 44, 48, 49, 50, 44, 51, 52, 53, 44, 54, 55, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 49, 46, 49, 50, 51 },
+        { 49, 50, 46, 49, 50, 51 },
+        { 49, 50, 51, 46, 49, 50, 51 },
+        { 49, 44, 50, 51, 52, 46, 49, 50, 51 },
+        { 49, 50, 44, 51, 52, 53, 46, 49, 50, 51 },
+        { 49, 50, 51, 44, 52, 53, 54, 46, 49, 50, 51 },
+        { 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 49, 50, 51 },
+        { 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 49, 50, 51 },
+        { 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 49, 50, 51 },
+        { 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 49, 50, 51 },
+        { 45, 49, 46, 49, 50, 51 },
+        { 45, 49, 50, 46, 49, 50, 51 },
+        { 45, 49, 50, 51, 46, 49, 50, 51 },
+        { 45, 49, 44, 50, 51, 52, 46, 49, 50, 51 },
+        { 45, 49, 50, 44, 51, 52, 53, 46, 49, 50, 51 },
+        { 45, 49, 50, 51, 44, 52, 53, 54, 46, 49, 50, 51 },
+        { 45, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 49, 50, 51 },
+        { 45, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 49, 50, 51 },
+        { 45, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 49, 50, 51 },
+        { 45, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 49, 50, 51 },
+        { 48, 46, 49 },
+        { 48, 46, 49, 50 },
+        { 48, 46, 49, 50, 51 },
+        { 48, 46, 49, 50, 51 },
+        { 49, 48, 46, 49 },
+        { 49, 48, 46, 49, 50 },
+        { 49, 48, 46, 49, 50, 51 },
+        { 49, 48, 46, 49, 50, 51 },
+        { 49, 48, 48, 46, 49 },
+        { 49, 48, 48, 46, 49, 50 },
+        { 49, 48, 48, 46, 49, 50, 51 },
+        { 49, 48, 48, 46, 49, 50, 51 },
+        { 49, 44, 48, 48, 48, 46, 49 },
+        { 49, 44, 48, 48, 48, 46, 49, 50 },
+        { 49, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 49, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 49, 48, 44, 48, 48, 48, 46, 49 },
+        { 49, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 49, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 49, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 49, 48, 48, 44, 48, 48, 48, 46, 49 },
+        { 49, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 49, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 49, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 },
+        { 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 },
+        { 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 },
+        { 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 },
+        { 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 45, 48, 46, 49 },
+        { 45, 48, 46, 49, 50 },
+        { 45, 48, 46, 49, 50, 51 },
+        { 45, 48, 46, 49, 50, 51 },
+        { 45, 49, 48, 46, 49 },
+        { 45, 49, 48, 46, 49, 50 },
+        { 45, 49, 48, 46, 49, 50, 51 },
+        { 45, 49, 48, 46, 49, 50, 51 },
+        { 45, 49, 48, 48, 46, 49 },
+        { 45, 49, 48, 48, 46, 49, 50 },
+        { 45, 49, 48, 48, 46, 49, 50, 51 },
+        { 45, 49, 48, 48, 46, 49, 50, 51 },
+        { 45, 49, 44, 48, 48, 48, 46, 49 },
+        { 45, 49, 44, 48, 48, 48, 46, 49, 50 },
+        { 45, 49, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 45, 49, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 45, 49, 48, 44, 48, 48, 48, 46, 49 },
+        { 45, 49, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 45, 49, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 45, 49, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 45, 49, 48, 48, 44, 48, 48, 48, 46, 49 },
+        { 45, 49, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 45, 49, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 45, 49, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 },
+        { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 45, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 },
+        { 45, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 45, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 45, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 45, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 },
+        { 45, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 45, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 45, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49 },
+        { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 51 },
+        { 49, 46, 57, 57, 57 },
+        { 49, 50, 46, 57, 57, 57 },
+        { 49, 50, 51, 46, 57, 57, 57 },
+        { 49, 44, 50, 51, 52, 46, 57, 57, 57 },
+        { 49, 50, 44, 51, 52, 53, 46, 57, 57, 57 },
+        { 49, 50, 51, 44, 52, 53, 54, 46, 57, 57, 57 },
+        { 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 57, 57, 57 },
+        { 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 57, 57, 57 },
+        { 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 57, 57, 57 },
+        { 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 57, 57, 57 },
+        { 50 },
+        { 49, 51 },
+        { 49, 50, 52 },
+        { 49, 44, 50, 51, 53 },
+        { 49, 50, 44, 51, 52, 54 },
+        { 49, 50, 51, 44, 52, 53, 55 },
+        { 49, 44, 50, 51, 52, 44, 53, 54, 56 },
+        { 49, 50, 44, 51, 52, 53, 44, 54, 55, 57 },
+        { 49, 50, 51, 44, 52, 53, 54, 44, 55, 57, 48 },
+        { 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 49 },
+        { 45, 49, 46, 57, 57, 57 },
+        { 45, 49, 50, 46, 57, 57, 57 },
+        { 45, 49, 50, 51, 46, 57, 57, 57 },
+        { 45, 49, 44, 50, 51, 52, 46, 57, 57, 57 },
+        { 45, 49, 50, 44, 51, 52, 53, 46, 57, 57, 57 },
+        { 45, 49, 50, 51, 44, 52, 53, 54, 46, 57, 57, 57 },
+        { 45, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 57, 57, 57 },
+        { 45, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 57, 57, 57 },
+        { 45, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 57, 57, 57 },
+        { 45, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 57, 57, 57 },
+        { 45, 50 },
+        { 45, 49, 51 },
+        { 45, 49, 50, 52 },
+        { 45, 49, 44, 50, 51, 53 },
+        { 45, 49, 50, 44, 51, 52, 54 },
+        { 45, 49, 50, 51, 44, 52, 53, 55 },
+        { 45, 49, 44, 50, 51, 52, 44, 53, 54, 56 },
+        { 45, 49, 50, 44, 51, 52, 53, 44, 54, 55, 57 },
+        { 45, 49, 50, 51, 44, 52, 53, 54, 44, 55, 57, 48 },
+        { 45, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 49 },
+        { 49, 49, 48 },
+        { 49, 44, 49, 48, 48 },
+        { 49, 49, 44, 48, 48, 48 },
+        { 49, 49, 48, 44, 48, 48, 48 },
+        { 49, 44, 49, 48, 48, 44, 48, 48, 48 },
+        { 49, 49, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 49, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 49, 44, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 45, 49, 49, 48 },
+        { 45, 49, 44, 49, 48, 48 },
+        { 45, 49, 49, 44, 48, 48, 48 },
+        { 45, 49, 49, 48, 44, 48, 48, 48 },
+        { 45, 49, 44, 49, 48, 48, 44, 48, 48, 48 },
+        { 45, 49, 49, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 45, 49, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 45, 49, 44, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 50 },
+        { 50, 48 },
+        { 50, 48, 48 },
+        { 50, 44, 48, 48, 48 },
+        { 50, 48, 44, 48, 48, 48 },
+        { 50, 48, 48, 44, 48, 48, 48 },
+        { 50, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 50, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 50, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 50, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 45, 50 },
+        { 45, 50, 48 },
+        { 45, 50, 48, 48 },
+        { 45, 50, 44, 48, 48, 48 },
+        { 45, 50, 48, 44, 48, 48, 48 },
+        { 45, 50, 48, 48, 44, 48, 48, 48 },
+        { 45, 50, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 45, 50, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 45, 50, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 45, 50, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 49, 48 },
+        { 49, 48, 48 },
+        { 49, 44, 48, 48, 48 },
+        { 49, 48, 44, 48, 48, 48 },
+        { 49, 48, 48, 44, 48, 48, 48 },
+        { 49, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 49, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 57, 46, 57, 57, 57 },
+        { 57, 57, 46, 57, 57, 57 },
+        { 57, 57, 57, 46, 57, 57, 57 },
+        { 57, 44, 57, 57, 57, 46, 57, 57, 57 },
+        { 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 },
+        { 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 },
+        { 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 },
+        { 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 },
+        { 57, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 },
+        { 45, 49, 48 },
+        { 45, 49, 48, 48 },
+        { 45, 49, 44, 48, 48, 48 },
+        { 45, 49, 48, 44, 48, 48, 48 },
+        { 45, 49, 48, 48, 44, 48, 48, 48 },
+        { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 45, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 45, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 45, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48 },
+        { 45, 57, 46, 57, 57, 57 },
+        { 45, 57, 57, 46, 57, 57, 57 },
+        { 45, 57, 57, 57, 46, 57, 57, 57 },
+        { 45, 57, 44, 57, 57, 57, 46, 57, 57, 57 },
+        { 45, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 },
+        { 45, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 },
+        { 45, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 },
+        { 45, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 },
+        { 45, 57, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 },
+        { 49 },
+        { 49, 50 },
+        { 49, 50, 51 },
+        { 49, 44, 50, 51, 52 },
+        { 49, 50, 44, 51, 52, 53 },
+        { 49, 50, 51, 44, 52, 53, 54 },
+        { 49, 44, 50, 51, 52, 44, 53, 54, 55 },
+        { 49, 50, 44, 51, 52, 53, 44, 54, 55, 56 },
+        { 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57 },
+        { 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48 },
+        { 45, 49 },
+        { 45, 49, 50 },
+        { 45, 49, 50, 51 },
+        { 45, 49, 44, 50, 51, 52 },
+        { 45, 49, 50, 44, 51, 52, 53 },
+        { 45, 49, 50, 51, 44, 52, 53, 54 },
+        { 45, 49, 44, 50, 51, 52, 44, 53, 54, 55 },
+        { 45, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56 },
+        { 45, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57 },
+        { 45, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48 },
+        { 45, 50, 44, 53, 57, 57, 46, 52 },
+        { 45, 50, 44, 53, 57, 57, 46, 51, 52 },
+        { 45, 50, 44, 53, 57, 57, 46, 51, 51, 52 },
+        { 49 },
+        { 49 },
+        { 49 },
+        { 49 },
+        { 49 },
+        { 49, 46, 48, 48, 49 },
+        { 49, 46, 48, 48, 49 },
+        { 49, 46, 48, 48, 49 },
+        { 49, 46, 48, 48, 49 },
+        { 49, 46, 48, 48, 49 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 50 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 46, 50, 50, 51 },
+        { 49, 48, 48, 44, 57, 49, 51, 46, 54, 55, 49 },
+        { 49, 57, 57, 44, 57, 57, 57, 46, 57, 57, 57 },
+        { 50, 53, 49, 44, 56, 52, 54, 46, 51, 52, 55 },
+        { 50, 53, 51, 44, 50, 52, 51, 46, 56, 56, 51 },
+        { 51, 54, 53, 44, 48, 52, 53, 46, 56, 53, 51 },
+        { 51, 49, 52, 44, 55, 51, 52, 46, 57, 54, 49 },
+        { 53, 52, 49, 44, 49, 51, 51, 46, 57, 55, 53 },
+        { 56, 53, 56, 44, 51, 55, 50, 46, 49, 50, 51 },
+        { 49, 44, 48, 48, 49, 44, 48, 48, 48 },
+        { 49, 44, 51, 52, 55, 44, 53, 48, 53, 46, 55, 56, 50 },
+        { 51, 44, 51, 53, 56, 44, 56, 52, 52, 46, 49, 57, 55 },
+        { 57, 44, 57, 57, 55, 44, 57, 55, 57, 46, 52, 48, 57 },
+        { 57, 44, 57, 57, 51, 44, 55, 52, 51, 46, 49, 53, 57 },
+        { 57, 44, 57, 51, 56, 44, 54, 55, 49, 46, 57, 48, 57 },
+        { 51, 44, 51, 56, 53, 44, 51, 48, 50, 46, 53, 52, 55 },
+        { 51, 44, 52, 48, 52, 44, 54, 52, 50, 46, 54, 54, 49 },
+        { 51, 44, 52, 51, 49, 44, 50, 56, 48, 46, 48, 56, 55 },
+        { 51, 44, 52, 51, 56, 44, 55, 53, 54, 46, 52, 55, 53 },
+        { 51, 44, 52, 52, 54, 44, 48, 53, 51, 46, 55, 56, 55 },
+        { 51, 44, 52, 53, 55, 44, 57, 49, 55, 46, 53, 49, 51 },
+        { 51, 44, 52, 54, 53, 44, 51, 57, 51, 46, 57, 48, 49 },
+        { 51, 44, 52, 56, 52, 44, 55, 51, 52, 46, 48, 49, 53 },
+        { 51, 44, 52, 57, 50, 44, 48, 51, 49, 46, 51, 50, 55 },
+        { 51, 44, 53, 48, 51, 44, 56, 57, 53, 46, 48, 53, 51 },
+        { 51, 44, 53, 49, 49, 44, 51, 55, 49, 46, 52, 52, 49 },
+        { 51, 44, 53, 49, 56, 44, 54, 54, 56, 46, 55, 53, 51 },
+        { 51, 44, 53, 51, 48, 44, 53, 51, 50, 46, 52, 55, 57 },
+        { 51, 44, 53, 51, 56, 44, 48, 48, 56, 46, 56, 54, 55 },
+        { 51, 44, 53, 52, 53, 44, 51, 48, 54, 46, 49, 55, 57 },
+        { 51, 44, 53, 53, 55, 44, 49, 54, 57, 46, 57, 48, 53 },
+        { 51, 44, 53, 53, 55, 44, 51, 52, 56, 46, 57, 56, 49 },
+        { 51, 44, 53, 54, 52, 44, 54, 52, 54, 46, 50, 57, 51 },
+        { 51, 44, 53, 56, 51, 44, 57, 56, 54, 46, 52, 48, 55 },
+        { 51, 44, 53, 57, 49, 44, 50, 56, 51, 46, 55, 49, 57 },
+        { 51, 44, 54, 48, 51, 44, 49, 52, 55, 46, 52, 52, 53 },
+        { 51, 44, 54, 49, 48, 44, 54, 50, 51, 46, 56, 51, 51 },
+        { 51, 44, 54, 49, 55, 44, 57, 50, 49, 46, 49, 52, 53 },
+        { 51, 44, 54, 50, 57, 44, 55, 56, 52, 46, 56, 55, 49 },
+        { 51, 44, 54, 51, 55, 44, 50, 54, 49, 46, 50, 53, 57 },
+        { 51, 44, 54, 53, 54, 44, 52, 50, 50, 46, 50, 57, 55 },
+        { 51, 44, 54, 53, 54, 44, 54, 48, 49, 46, 51, 55, 51 },
+        { 51, 44, 54, 54, 51, 44, 56, 57, 56, 46, 54, 56, 53 },
+        { 51, 44, 54, 55, 53, 44, 55, 54, 50, 46, 52, 49, 49 },
+        { 51, 44, 54, 56, 51, 44, 50, 51, 56, 46, 55, 57, 57 },
+        { 51, 44, 54, 57, 48, 44, 53, 51, 54, 46, 49, 49, 49 },
+        { 51, 44, 55, 48, 50, 44, 51, 57, 57, 46, 56, 51, 55 },
+        { 51, 44, 55, 48, 57, 44, 56, 55, 54, 46, 50, 50, 53 },
+        { 51, 44, 55, 49, 55, 44, 49, 55, 51, 46, 53, 51, 55 },
+        { 51, 44, 55, 50, 57, 44, 48, 51, 55, 46, 50, 54, 51 },
+        { 51, 44, 55, 51, 54, 44, 53, 49, 51, 46, 54, 53, 49 },
+        { 51, 44, 55, 53, 53, 44, 56, 53, 51, 46, 55, 54, 53 },
+        { 51, 44, 55, 54, 51, 44, 49, 53, 49, 46, 48, 55, 55 },
+        { 51, 44, 55, 55, 53, 44, 48, 49, 52, 46, 56, 48, 51 },
+        { 51, 44, 55, 56, 50, 44, 52, 57, 49, 46, 49, 57, 49 },
+        { 51, 44, 55, 56, 57, 44, 55, 56, 56, 46, 53, 48, 51 },
+        { 51, 44, 56, 48, 49, 44, 54, 53, 50, 46, 50, 50, 57 },
+        { 51, 44, 56, 48, 57, 44, 49, 50, 56, 46, 54, 49, 55 },
+        { 51, 44, 56, 49, 54, 44, 52, 50, 53, 46, 57, 50, 57 },
+        { 51, 44, 56, 50, 56, 44, 50, 56, 57, 46, 54, 53, 53 },
+        { 51, 44, 56, 50, 56, 44, 52, 54, 56, 46, 55, 51, 49 },
+        { 51, 44, 56, 51, 53, 44, 55, 54, 54, 46, 48, 52, 51 },
+        { 51, 44, 56, 53, 53, 44, 49, 48, 54, 46, 49, 53, 55 },
+        { 51, 44, 56, 54, 50, 44, 52, 48, 51, 46, 52, 54, 57 },
+        { 51, 44, 56, 55, 52, 44, 50, 54, 55, 46, 49, 57, 53 },
+        { 51, 44, 56, 56, 49, 44, 55, 52, 51, 46, 53, 56, 51 },
+        { 51, 44, 56, 56, 57, 44, 48, 52, 48, 46, 56, 57, 53 },
+        { 51, 44, 57, 48, 48, 44, 57, 48, 52, 46, 54, 50, 49 },
+        { 51, 44, 57, 48, 56, 44, 51, 56, 49, 46, 48, 48, 57 },
+        { 51, 44, 57, 50, 55, 44, 53, 52, 50, 46, 48, 52, 55 },
+        { 51, 44, 57, 50, 55, 44, 55, 50, 49, 46, 49, 50, 51 },
+        { 51, 44, 57, 51, 53, 44, 48, 49, 56, 46, 52, 51, 53 },
+        { 51, 44, 57, 52, 54, 44, 56, 56, 50, 46, 49, 54, 49 },
+        { 51, 44, 57, 53, 52, 44, 51, 53, 56, 46, 53, 52, 57 },
+        { 51, 44, 57, 54, 49, 44, 54, 53, 53, 46, 56, 54, 49 },
+        { 51, 44, 57, 55, 51, 44, 53, 49, 57, 46, 53, 56, 55 },
+        { 51, 44, 57, 56, 48, 44, 57, 57, 53, 46, 57, 55, 53 },
+        { 51, 44, 57, 56, 56, 44, 50, 57, 51, 46, 50, 56, 55 },
+        { 52, 44, 48, 48, 48, 44, 49, 53, 55, 46, 48, 49, 51 },
+        { 52, 44, 48, 48, 55, 44, 54, 51, 51, 46, 52, 48, 49 },
+        { 52, 44, 48, 50, 54, 44, 57, 55, 51, 46, 53, 49, 53 },
+        { 52, 44, 48, 51, 52, 44, 50, 55, 48, 46, 56, 50, 55 },
+        { 52, 44, 48, 52, 54, 44, 49, 51, 52, 46, 53, 53, 51 },
+        { 52, 44, 48, 53, 51, 44, 54, 49, 48, 46, 57, 52, 49 },
+        { 52, 44, 48, 54, 48, 44, 57, 48, 56, 46, 50, 53, 51 },
+        { 52, 44, 48, 55, 50, 44, 55, 55, 49, 46, 57, 55, 57 },
+        { 52, 44, 48, 56, 48, 44, 50, 52, 56, 46, 51, 54, 55 },
+        { 52, 44, 48, 56, 55, 44, 53, 52, 53, 46, 54, 55, 57 },
+        { 52, 44, 48, 57, 57, 44, 52, 48, 57, 46, 52, 48, 53 },
+        { 52, 44, 48, 57, 57, 44, 53, 56, 56, 46, 52, 56, 49 },
+        { 52, 44, 49, 48, 54, 44, 56, 56, 53, 46, 55, 57, 51 },
+        { 52, 44, 49, 50, 54, 44, 50, 50, 53, 46, 57, 48, 55 },
+        { 52, 44, 49, 51, 51, 44, 53, 50, 51, 46, 50, 49, 57 },
+        { 52, 44, 49, 52, 53, 44, 51, 56, 54, 46, 57, 52, 53 },
+        { 52, 44, 49, 53, 50, 44, 56, 54, 51, 46, 51, 51, 51 },
+        { 52, 44, 49, 54, 48, 44, 49, 54, 48, 46, 54, 52, 53 },
+        { 52, 44, 49, 55, 50, 44, 48, 50, 52, 46, 51, 55, 49 },
+        { 52, 44, 49, 55, 57, 44, 53, 48, 48, 46, 55, 53, 57 },
+        { 52, 44, 49, 57, 56, 44, 54, 54, 49, 46, 55, 57, 55 },
+        { 52, 44, 50, 48, 51, 44, 52, 48, 55, 46, 50, 56, 55 },
+        { 52, 44, 50, 49, 48, 44, 55, 48, 52, 46, 53, 57, 57 },
+        { 52, 44, 50, 49, 51, 44, 52, 51, 53, 46, 52, 57, 55 },
+    };
+
+    // The array of int[] unicode values storing the expected results
+    // when calling Decimal.format(double) on the currency GoldenDoubleValues.
+    static int[][] CurrencyGoldenFormattedValues = {
+        { 36, 48, 46, 48, 48 },
+        { 40, 36, 48, 46, 48, 48, 41 },
+        { 36, 48, 46, 48, 48 },
+        { 36, 48, 46, 48, 48 },
+        { 40, 36, 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 54, 46, 50, 51, 41 },
+        { 36, 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 54, 46, 50, 51 },
+        { 40, 36, 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 56, 46, 48, 48, 41 },
+        { 36, 50, 44, 49, 52, 55, 44, 52, 56, 51, 44, 54, 52, 56, 46, 48, 48 },
+        { 40, 36, 49, 44, 57, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 41 },
+        { 36, 50, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 65533 },
+        { 36, 8734 },
+        { 40, 36, 8734, 41 },
+        { 36, 49, 55, 57, 44, 55, 54, 57, 44, 51, 49, 51, 44, 52, 56, 54, 44, 50, 51, 49, 44, 53, 55, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 40, 36, 57, 44, 56, 55, 54, 44, 53, 52, 51, 44, 50, 49, 48, 46, 57, 57, 41 },
+        { 36, 57, 44, 56, 55, 54, 44, 53, 52, 51, 44, 50, 49, 48, 46, 57, 57 },
+        { 40, 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 44, 48, 49, 50, 44, 51, 52, 53, 44, 54, 55, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 44, 48, 49, 50, 44, 51, 52, 53, 44, 54, 55, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 49, 46, 49, 50 },
+        { 36, 49, 50, 46, 49, 50 },
+        { 36, 49, 50, 51, 46, 49, 50 },
+        { 36, 49, 44, 50, 51, 52, 46, 49, 50 },
+        { 36, 49, 50, 44, 51, 52, 53, 46, 49, 50 },
+        { 36, 49, 50, 51, 44, 52, 53, 54, 46, 49, 50 },
+        { 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 49, 50 },
+        { 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 49, 50 },
+        { 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 49, 50 },
+        { 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 49, 50 },
+        { 40, 36, 49, 46, 49, 50, 41 },
+        { 40, 36, 49, 50, 46, 49, 50, 41 },
+        { 40, 36, 49, 50, 51, 46, 49, 50, 41 },
+        { 40, 36, 49, 44, 50, 51, 52, 46, 49, 50, 41 },
+        { 40, 36, 49, 50, 44, 51, 52, 53, 46, 49, 50, 41 },
+        { 40, 36, 49, 50, 51, 44, 52, 53, 54, 46, 49, 50, 41 },
+        { 40, 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 49, 50, 41 },
+        { 40, 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 49, 50, 41 },
+        { 40, 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 49, 50, 41 },
+        { 40, 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 49, 50, 41 },
+        { 36, 48, 46, 49, 48 },
+        { 36, 48, 46, 49, 50 },
+        { 36, 48, 46, 49, 50 },
+        { 36, 49, 48, 46, 49, 48 },
+        { 36, 49, 48, 46, 49, 50 },
+        { 36, 49, 48, 46, 49, 50 },
+        { 36, 49, 48, 48, 46, 49, 48 },
+        { 36, 49, 48, 48, 46, 49, 50 },
+        { 36, 49, 48, 48, 46, 49, 50 },
+        { 36, 49, 44, 48, 48, 48, 46, 49, 48 },
+        { 36, 49, 44, 48, 48, 48, 46, 49, 50 },
+        { 36, 49, 44, 48, 48, 48, 46, 49, 50 },
+        { 36, 49, 48, 44, 48, 48, 48, 46, 49, 48 },
+        { 36, 49, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 36, 49, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 36, 49, 48, 48, 44, 48, 48, 48, 46, 49, 48 },
+        { 36, 49, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 36, 49, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48 },
+        { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48 },
+        { 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48 },
+        { 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48 },
+        { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50 },
+        { 40, 36, 48, 46, 49, 48, 41 },
+        { 40, 36, 48, 46, 49, 50, 41 },
+        { 40, 36, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 48, 46, 49, 48, 41 },
+        { 40, 36, 49, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 48, 48, 46, 49, 48, 41 },
+        { 40, 36, 49, 48, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 48, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 44, 48, 48, 48, 46, 49, 48, 41 },
+        { 40, 36, 49, 44, 48, 48, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 44, 48, 48, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 48, 44, 48, 48, 48, 46, 49, 48, 41 },
+        { 40, 36, 49, 48, 44, 48, 48, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 48, 44, 48, 48, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 48, 48, 44, 48, 48, 48, 46, 49, 48, 41 },
+        { 40, 36, 49, 48, 48, 44, 48, 48, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 48, 48, 44, 48, 48, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48, 41 },
+        { 40, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48, 41 },
+        { 40, 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48, 41 },
+        { 40, 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 48, 41 },
+        { 40, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 41 },
+        { 40, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 49, 50, 41 },
+        { 36, 49, 46, 57, 57 },
+        { 36, 49, 50, 46, 57, 57 },
+        { 36, 49, 50, 51, 46, 57, 57 },
+        { 36, 49, 44, 50, 51, 52, 46, 57, 57 },
+        { 36, 49, 50, 44, 51, 52, 53, 46, 57, 57 },
+        { 36, 49, 50, 51, 44, 52, 53, 54, 46, 57, 57 },
+        { 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 57, 57 },
+        { 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 57, 57 },
+        { 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 57, 57 },
+        { 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 57, 57 },
+        { 36, 50, 46, 48, 48 },
+        { 36, 49, 51, 46, 48, 48 },
+        { 36, 49, 50, 52, 46, 48, 48 },
+        { 36, 49, 44, 50, 51, 53, 46, 48, 48 },
+        { 36, 49, 50, 44, 51, 52, 54, 46, 48, 48 },
+        { 36, 49, 50, 51, 44, 52, 53, 55, 46, 48, 48 },
+        { 36, 49, 44, 50, 51, 52, 44, 53, 54, 56, 46, 48, 48 },
+        { 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 57, 46, 48, 48 },
+        { 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 57, 48, 46, 48, 48 },
+        { 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 49, 46, 48, 48 },
+        { 40, 36, 49, 46, 57, 57, 41 },
+        { 40, 36, 49, 50, 46, 57, 57, 41 },
+        { 40, 36, 49, 50, 51, 46, 57, 57, 41 },
+        { 40, 36, 49, 44, 50, 51, 52, 46, 57, 57, 41 },
+        { 40, 36, 49, 50, 44, 51, 52, 53, 46, 57, 57, 41 },
+        { 40, 36, 49, 50, 51, 44, 52, 53, 54, 46, 57, 57, 41 },
+        { 40, 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 57, 57, 41 },
+        { 40, 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 57, 57, 41 },
+        { 40, 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 57, 57, 41 },
+        { 40, 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 57, 57, 41 },
+        { 40, 36, 50, 46, 48, 48, 41 },
+        { 40, 36, 49, 51, 46, 48, 48, 41 },
+        { 40, 36, 49, 50, 52, 46, 48, 48, 41 },
+        { 40, 36, 49, 44, 50, 51, 53, 46, 48, 48, 41 },
+        { 40, 36, 49, 50, 44, 51, 52, 54, 46, 48, 48, 41 },
+        { 40, 36, 49, 50, 51, 44, 52, 53, 55, 46, 48, 48, 41 },
+        { 40, 36, 49, 44, 50, 51, 52, 44, 53, 54, 56, 46, 48, 48, 41 },
+        { 40, 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 57, 46, 48, 48, 41 },
+        { 40, 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 57, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 49, 46, 48, 48, 41 },
+        { 36, 49, 49, 48, 46, 48, 48 },
+        { 36, 49, 44, 49, 48, 48, 46, 48, 48 },
+        { 36, 49, 49, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 49, 49, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 49, 44, 49, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 49, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 49, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 49, 44, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 40, 36, 49, 49, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 44, 49, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 49, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 49, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 44, 49, 48, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 44, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 36, 50, 46, 48, 48 },
+        { 36, 50, 48, 46, 48, 48 },
+        { 36, 50, 48, 48, 46, 48, 48 },
+        { 36, 50, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 50, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 50, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 50, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 50, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 50, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 50, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 40, 36, 50, 46, 48, 48, 41 },
+        { 40, 36, 50, 48, 46, 48, 48, 41 },
+        { 40, 36, 50, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 50, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 50, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 50, 48, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 50, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 50, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 50, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 50, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 36, 49, 48, 46, 48, 48 },
+        { 36, 49, 48, 48, 46, 48, 48 },
+        { 36, 49, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 49, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 49, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48 },
+        { 36, 57, 46, 57, 57 },
+        { 36, 57, 57, 46, 57, 57 },
+        { 36, 57, 57, 57, 46, 57, 57 },
+        { 36, 57, 44, 57, 57, 57, 46, 57, 57 },
+        { 36, 57, 57, 44, 57, 57, 57, 46, 57, 57 },
+        { 36, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57 },
+        { 36, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57 },
+        { 36, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57 },
+        { 36, 57, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57 },
+        { 40, 36, 49, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 48, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 49, 44, 48, 48, 48, 44, 48, 48, 48, 44, 48, 48, 48, 46, 48, 48, 41 },
+        { 40, 36, 57, 46, 57, 57, 41 },
+        { 40, 36, 57, 57, 46, 57, 57, 41 },
+        { 40, 36, 57, 57, 57, 46, 57, 57, 41 },
+        { 40, 36, 57, 44, 57, 57, 57, 46, 57, 57, 41 },
+        { 40, 36, 57, 57, 44, 57, 57, 57, 46, 57, 57, 41 },
+        { 40, 36, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 41 },
+        { 40, 36, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 41 },
+        { 40, 36, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 41 },
+        { 40, 36, 57, 57, 57, 44, 57, 57, 57, 44, 57, 57, 57, 46, 57, 57, 41 },
+        { 36, 49, 46, 48, 48 },
+        { 36, 49, 50, 46, 48, 48 },
+        { 36, 49, 50, 51, 46, 48, 48 },
+        { 36, 49, 44, 50, 51, 52, 46, 48, 48 },
+        { 36, 49, 50, 44, 51, 52, 53, 46, 48, 48 },
+        { 36, 49, 50, 51, 44, 52, 53, 54, 46, 48, 48 },
+        { 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 48, 48 },
+        { 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 48, 48 },
+        { 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 48, 48 },
+        { 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 48, 48 },
+        { 40, 36, 49, 46, 48, 48, 41 },
+        { 40, 36, 49, 50, 46, 48, 48, 41 },
+        { 40, 36, 49, 50, 51, 46, 48, 48, 41 },
+        { 40, 36, 49, 44, 50, 51, 52, 46, 48, 48, 41 },
+        { 40, 36, 49, 50, 44, 51, 52, 53, 46, 48, 48, 41 },
+        { 40, 36, 49, 50, 51, 44, 52, 53, 54, 46, 48, 48, 41 },
+        { 40, 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 46, 48, 48, 41 },
+        { 40, 36, 49, 50, 44, 51, 52, 53, 44, 54, 55, 56, 46, 48, 48, 41 },
+        { 40, 36, 49, 50, 51, 44, 52, 53, 54, 44, 55, 56, 57, 46, 48, 48, 41 },
+        { 40, 36, 49, 44, 50, 51, 52, 44, 53, 54, 55, 44, 56, 57, 48, 46, 48, 48, 41 },
+        { 40, 36, 50, 44, 53, 57, 57, 46, 52, 48, 41 },
+        { 40, 36, 50, 44, 53, 57, 57, 46, 51, 52, 41 },
+        { 40, 36, 50, 44, 53, 57, 57, 46, 51, 51, 41 },
+        { 36, 49, 46, 48, 48 },
+        { 36, 49, 46, 48, 48 },
+        { 36, 49, 46, 48, 48 },
+        { 36, 49, 46, 48, 48 },
+        { 36, 49, 46, 48, 48 },
+        { 36, 49, 46, 48, 49 },
+        { 36, 49, 46, 48, 49 },
+        { 36, 49, 46, 48, 49 },
+        { 36, 49, 46, 48, 49 },
+        { 36, 49, 46, 48, 49 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 50 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 46, 50, 51 },
+        { 36, 49, 44, 48, 48, 57, 44, 49, 51, 54, 46, 55, 49 },
+        { 36, 50, 44, 53, 49, 56, 44, 52, 54, 51, 46, 52, 54 },
+        { 36, 50, 44, 53, 51, 50, 44, 52, 51, 56, 46, 56, 51 },
+        { 36, 51, 44, 54, 53, 48, 44, 52, 53, 56, 46, 53, 51 },
+        { 36, 51, 44, 49, 52, 55, 44, 51, 52, 57, 46, 54, 50 },
+        { 36, 53, 44, 52, 49, 49, 44, 51, 51, 57, 46, 55, 53 },
+        { 36, 56, 44, 53, 56, 51, 44, 55, 50, 49, 46, 50, 50 },
+        { 36, 49, 51, 44, 52, 55, 53, 44, 48, 53, 55, 46, 56, 50 },
+        { 36, 51, 51, 44, 53, 56, 56, 44, 52, 52, 49, 46, 57, 56 },
+        { 36, 57, 57, 44, 57, 55, 57, 44, 55, 57, 52, 46, 48, 56 },
+        { 36, 57, 57, 44, 57, 51, 55, 44, 52, 51, 49, 46, 53, 56 },
+        { 36, 57, 57, 44, 51, 56, 54, 44, 55, 49, 57, 46, 48, 56 },
+        { 36, 51, 51, 44, 56, 53, 51, 44, 48, 50, 53, 46, 52, 55 },
+        { 36, 51, 52, 44, 48, 52, 54, 44, 52, 50, 54, 46, 54, 48 },
+        { 36, 51, 52, 44, 51, 49, 50, 44, 56, 48, 48, 46, 56, 55 },
+        { 36, 51, 52, 44, 51, 56, 55, 44, 53, 54, 52, 46, 55, 53 },
+        { 36, 51, 52, 44, 52, 54, 48, 44, 53, 51, 55, 46, 56, 55 },
+        { 36, 51, 52, 44, 53, 55, 57, 44, 49, 55, 53, 46, 49, 50 },
+        { 36, 51, 52, 44, 54, 53, 51, 44, 57, 51, 57, 46, 48, 50 },
+        { 36, 51, 52, 44, 56, 52, 55, 44, 51, 52, 48, 46, 49, 53 },
+        { 36, 51, 52, 44, 57, 50, 48, 44, 51, 49, 51, 46, 50, 55 },
+        { 36, 51, 53, 44, 48, 51, 56, 44, 57, 53, 48, 46, 53, 50 },
+        { 36, 51, 53, 44, 49, 49, 51, 44, 55, 49, 52, 46, 52, 49 },
+        { 36, 51, 53, 44, 49, 56, 54, 44, 54, 56, 55, 46, 53, 51 },
+        { 36, 51, 53, 44, 51, 48, 53, 44, 51, 50, 52, 46, 55, 56 },
+        { 36, 51, 53, 44, 51, 56, 48, 44, 48, 56, 56, 46, 54, 55 },
+        { 36, 51, 53, 44, 52, 53, 51, 44, 48, 54, 49, 46, 55, 57 },
+        { 36, 51, 53, 44, 53, 55, 49, 44, 54, 57, 57, 46, 48, 53 },
+        { 36, 51, 53, 44, 53, 55, 51, 44, 52, 56, 57, 46, 56, 49 },
+        { 36, 51, 53, 44, 54, 52, 54, 44, 52, 54, 50, 46, 57, 51 },
+        { 36, 51, 53, 44, 56, 51, 57, 44, 56, 54, 52, 46, 48, 55 },
+        { 36, 51, 53, 44, 57, 49, 50, 44, 56, 51, 55, 46, 50, 48 },
+        { 36, 51, 54, 44, 48, 51, 49, 44, 52, 55, 52, 46, 52, 53 },
+        { 36, 51, 54, 44, 49, 48, 54, 44, 50, 51, 56, 46, 51, 51 },
+        { 36, 51, 54, 44, 49, 55, 57, 44, 50, 49, 49, 46, 52, 53 },
+        { 36, 51, 54, 44, 50, 57, 55, 44, 56, 52, 56, 46, 55, 48 },
+        { 36, 51, 54, 44, 51, 55, 50, 44, 54, 49, 50, 46, 53, 57 },
+        { 36, 51, 54, 44, 53, 54, 52, 44, 50, 50, 50, 46, 57, 55 },
+        { 36, 51, 54, 44, 53, 54, 54, 44, 48, 49, 51, 46, 55, 51 },
+        { 36, 51, 54, 44, 54, 51, 56, 44, 57, 56, 54, 46, 56, 53 },
+        { 36, 51, 54, 44, 55, 53, 55, 44, 54, 50, 52, 46, 49, 48 },
+        { 36, 51, 54, 44, 56, 51, 50, 44, 51, 56, 55, 46, 57, 57 },
+        { 36, 51, 54, 44, 57, 48, 53, 44, 51, 54, 49, 46, 49, 49 },
+        { 36, 51, 55, 44, 48, 50, 51, 44, 57, 57, 56, 46, 51, 55 },
+        { 36, 51, 55, 44, 48, 57, 56, 44, 55, 54, 50, 46, 50, 53 },
+        { 36, 51, 55, 44, 49, 55, 49, 44, 55, 51, 53, 46, 51, 55 },
+        { 36, 51, 55, 44, 50, 57, 48, 44, 51, 55, 50, 46, 54, 50 },
+        { 36, 51, 55, 44, 51, 54, 53, 44, 49, 51, 54, 46, 53, 50 },
+        { 36, 51, 55, 44, 53, 53, 56, 44, 53, 51, 55, 46, 54, 53 },
+        { 36, 51, 55, 44, 54, 51, 49, 44, 53, 49, 48, 46, 55, 55 },
+        { 36, 51, 55, 44, 55, 53, 48, 44, 49, 52, 56, 46, 48, 50 },
+        { 36, 51, 55, 44, 56, 50, 52, 44, 57, 49, 49, 46, 57, 49 },
+        { 36, 51, 55, 44, 56, 57, 55, 44, 56, 56, 53, 46, 48, 51 },
+        { 36, 51, 56, 44, 48, 49, 54, 44, 53, 50, 50, 46, 50, 56 },
+        { 36, 51, 56, 44, 48, 57, 49, 44, 50, 56, 54, 46, 49, 55 },
+        { 36, 51, 56, 44, 49, 54, 52, 44, 50, 53, 57, 46, 50, 57 },
+        { 36, 51, 56, 44, 50, 56, 50, 44, 56, 57, 54, 46, 53, 53 },
+        { 36, 51, 56, 44, 50, 56, 52, 44, 54, 56, 55, 46, 51, 49 },
+        { 36, 51, 56, 44, 51, 53, 55, 44, 54, 54, 48, 46, 52, 51 },
+        { 36, 51, 56, 44, 53, 53, 49, 44, 48, 54, 49, 46, 53, 55 },
+        { 36, 51, 56, 44, 54, 50, 52, 44, 48, 51, 52, 46, 55, 48 },
+        { 36, 51, 56, 44, 55, 52, 50, 44, 54, 55, 49, 46, 57, 53 },
+        { 36, 51, 56, 44, 56, 49, 55, 44, 52, 51, 53, 46, 56, 51 },
+        { 36, 51, 56, 44, 56, 57, 48, 44, 52, 48, 56, 46, 57, 53 },
+        { 36, 51, 57, 44, 48, 48, 57, 44, 48, 52, 54, 46, 50, 48 },
+        { 36, 51, 57, 44, 48, 56, 51, 44, 56, 49, 48, 46, 48, 57 },
+        { 36, 51, 57, 44, 50, 55, 53, 44, 52, 50, 48, 46, 52, 55 },
+        { 36, 51, 57, 44, 50, 55, 55, 44, 50, 49, 49, 46, 50, 51 },
+        { 36, 51, 57, 44, 51, 53, 48, 44, 49, 56, 52, 46, 51, 53 },
+        { 36, 51, 57, 44, 52, 54, 56, 44, 56, 50, 49, 46, 54, 48 },
+        { 36, 51, 57, 44, 53, 52, 51, 44, 53, 56, 53, 46, 52, 57 },
+        { 36, 51, 57, 44, 54, 49, 54, 44, 53, 53, 56, 46, 54, 49 },
+        { 36, 51, 57, 44, 55, 51, 53, 44, 49, 57, 53, 46, 56, 55 },
+        { 36, 51, 57, 44, 56, 48, 57, 44, 57, 53, 57, 46, 55, 53 },
+        { 36, 51, 57, 44, 56, 56, 50, 44, 57, 51, 50, 46, 56, 55 },
+        { 36, 52, 48, 44, 48, 48, 49, 44, 53, 55, 48, 46, 49, 50 },
+        { 36, 52, 48, 44, 48, 55, 54, 44, 51, 51, 52, 46, 48, 50 },
+        { 36, 52, 48, 44, 50, 54, 57, 44, 55, 51, 53, 46, 49, 53 },
+        { 36, 52, 48, 44, 51, 52, 50, 44, 55, 48, 56, 46, 50, 55 },
+        { 36, 52, 48, 44, 52, 54, 49, 44, 51, 52, 53, 46, 53, 50 },
+        { 36, 52, 48, 44, 53, 51, 54, 44, 49, 48, 57, 46, 52, 49 },
+        { 36, 52, 48, 44, 54, 48, 57, 44, 48, 56, 50, 46, 53, 51 },
+        { 36, 52, 48, 44, 55, 50, 55, 44, 55, 49, 57, 46, 55, 56 },
+        { 36, 52, 48, 44, 56, 48, 50, 44, 52, 56, 51, 46, 54, 55 },
+        { 36, 52, 48, 44, 56, 55, 53, 44, 52, 53, 54, 46, 55, 57 },
+        { 36, 52, 48, 44, 57, 57, 52, 44, 48, 57, 52, 46, 48, 53 },
+        { 36, 52, 48, 44, 57, 57, 53, 44, 56, 56, 52, 46, 56, 49 },
+        { 36, 52, 49, 44, 48, 54, 56, 44, 56, 53, 55, 46, 57, 51 },
+        { 36, 52, 49, 44, 50, 54, 50, 44, 50, 53, 57, 46, 48, 55 },
+        { 36, 52, 49, 44, 51, 51, 53, 44, 50, 51, 50, 46, 50, 48 },
+        { 36, 52, 49, 44, 52, 53, 51, 44, 56, 54, 57, 46, 52, 53 },
+        { 36, 52, 49, 44, 53, 50, 56, 44, 54, 51, 51, 46, 51, 51 },
+        { 36, 52, 49, 44, 54, 48, 49, 44, 54, 48, 54, 46, 52, 53 },
+        { 36, 52, 49, 44, 55, 50, 48, 44, 50, 52, 51, 46, 55, 48 },
+        { 36, 52, 49, 44, 55, 57, 53, 44, 48, 48, 55, 46, 53, 57 },
+        { 36, 52, 49, 44, 57, 56, 54, 44, 54, 49, 55, 46, 57, 55 },
+        { 36, 52, 50, 44, 48, 51, 52, 44, 48, 55, 50, 46, 56, 55 },
+        { 36, 52, 50, 44, 49, 48, 55, 44, 48, 52, 53, 46, 57, 56 },
+        { 36, 52, 50, 44, 49, 51, 52, 44, 51, 53, 52, 46, 57, 56 },
+    };
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DecimalFormat/RoundingAndPropertyTest.java	Tue Oct 02 10:11:57 2012 +0100
@@ -0,0 +1,795 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 7050528
+ * @summary Test java.text.DecimalFormat fast-path for format(double...)
+ * @author Olivier Lagneau
+ * @run main RoundingAndPropertyTest
+ *
+ */
+
+/* -----------------------------------------------------------------------------
+ * Note :
+ *  Since fast-path algorithm   does not modify  any feature  of DecimalFormat,
+ *  some tests or  values in this program  may have to be adapted/added/removed
+ *  when any change has been done in the fast-path source  code, because the
+ *  conditions for exercising fast-path may change.
+ *
+ *  This is specially true if the set of constraints to fall in the fast-path
+ *  case is relaxed in any manner.
+ *
+ * Usage :
+ *  - Run main without any argument to test against a set of golden values and
+ *    associated results hard-coded in the source code. That will do the tests
+ *    described below
+ *    See below comment section named "Description".
+ *
+ *  or
+ *
+ *  - Run main with string argument "-gengold" to output source code of
+ *    GoldenFormattedValues.java class file with the jdk version used while
+ *    generating the code.
+ *    See below comment section named : "Modifying Golden Values".
+ *
+ *  In case of error while running the test, a Runtime exception is generated
+ *  providing the numbers of errors detected (format of golden values checks and
+ *  property changes checks), and the program exit.
+ *
+ * Description :
+ *
+ *  This test first checks that localization of digits is done correctly when
+ *  calling DecimalFormat.format() on the array of values DecimalLocalizationValues
+ *  found in GoldenDoubleValues, using the locale FullLocalizationTestLocale
+ *  (from GoldenDoubleValues) that implies localization of digits. it checks the
+ *  the results against expected returned string. In case of formatting error,
+ *  it provides a message informing which value was wrongly formatted.
+ *
+ *  Then it checks the results of  calling NumberFormat.format(double) on a set
+ *  of  predefined golden values and  checks results against expected returned
+ *  string.  It does this both for the  decimal case, with an instance returned
+ *  NumberFormat.getInstance() call and for the currency case, with an instance
+ *  returned by NumberFormat.getCurrencyInstance(). Almost all the tested  double
+ *  values satisfy the constraints assumed by the fast-path algorithm for
+ *  format(double ...). Some  are voluntarily outside the scope of fast-path to
+ *  check that the algorithm correctly eliminate them. In case of formatting
+ *  error a message provides information on the golden value raising the error
+ *  (value, exact decimal value (using BidDecimal), expected result, formatted result).
+ *
+ *  Last  the test checks the status and  behavior of a DecimalFormat instance
+ *  when changing  properties that  make this  instance  satisfy/invalidate its
+ *  fast-path status, depending on the predefined  set of fast-path constraints.
+ *
+ *  The golden  results are predefined arrays  of  int[] containing the unicode
+ *  ints of the chars  in  the expected  formatted  string, when  using  locale
+ *  provided in  GoldenDoubleValues class. The   results are those obtained  by
+ *  using a reference jdk  version (for example  one that does not contains the
+ *  DecimalFormat fast-path algorithm, like jdk80-b25).
+ *
+ *  The double values from which we get golden results are stored inside two
+ *  arrays of double values:
+ *  - DecimalGoldenValues  for testing NumberFormat.getInstance().
+ *  - CurrencyGoldenValues for testing NumberFormat.getCurrencyInstance().
+ *  These arrays are located in GoldenDoubleValues.java source file.
+ *
+ *  For each double value in the arrays above, there is an associated golden
+ *  result. These results are stored in arrays of int[]:
+ *  - DecimalGoldenFormattedValues  for expected decimal golden results.
+ *  - CurrencyGoldenFormattedValues for expected currency golden results.
+ *  - DecimalDigitsLocalizedFormattedValues for expected localized digit results.
+ *
+ *  We store the results in int[] arrays containing the expected unicode values
+ *  because the  compiler that will compile the  containing java file may use a
+ *  different locale than the one registered in GoldenDoubleValues.java.  These
+ *  arrays are  located in  a  separate GoldenFormattedValues.java  source file
+ *  that is generated  by  RoundingAndPropertyTest using  "-gengold"  parameter.
+ *  See below "Modifying Golden Values".
+ *
+ *  The golden value arrays can be expanded, modified ... to test additional
+ *  or different double values. In that case, the source file of class
+ *  GoldenFormattedValues must be regenerated to replace the existing one..
+ *
+ * Modifying Golden Values :
+ *
+ *  In order to ease further modification of the list of double values checked
+ *  and associated golden results, the test includes the method
+ *  generatesGoldenFormattedValuesClass() that writes on standard output stream
+ *  the source code for GoldenFormattedValues class that includes the expected
+ *  results arrays.
+ *
+ *  Here are the steps to follow for updating/modifying golden values and results:
+ *   1- Edit GoldenDoubleValues.java to add/remove/modify golden or localization
+ *      values.
+ *   2- Run main with "-gengold" string argument with a target jdk.
+ *      (at the creation of this test file, the target jdk used was jdk1.8.0-ea).
+ *   2- Copy this java code that has been writen on standard output and replace
+ *      GoldenFormattedValues.java contents by the generated output.
+ *   3- Check that this updated code compiles.
+ *  [4]- If needed replaces existing GoldenDoubleValues and GoldenFormattedValues
+ *      files in jdk/test section, respectively by the one modified at step 1 and
+ *      generated at step 2.
+ * -----------------------------------------------------------------------------
+ */
+
+import java.util.*;
+import java.text.NumberFormat;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.math.RoundingMode;
+import java.math.BigDecimal;
+
+
+public class RoundingAndPropertyTest {
+
+
+    // Prints on standard output stream the unicode values of chars as a
+    // comma-separated list of int values
+    private static void printUnicodeValuesArray(char[] chars) {
+        for (int i = 0; i < chars.length; i++) {
+            System.out.print((int) chars[i]);
+            if (i != (chars.length - 1))
+                System.out.print(", ");
+        }
+    }
+
+    // Converts given array of unicode values as an array of chars.
+    // Returns this converted array.
+    private static char[] getCharsFromUnicodeArray(int[] unicodeValues) {
+        char[] chars = new char[unicodeValues.length];
+
+        for (int i = 0; i < unicodeValues.length; i++) {
+            chars[i] = (char) unicodeValues[i];
+        }
+        return chars;
+    }
+
+    /* Prints on standard output stream the java code of resulting
+     * GoldenFormattedValues class for the golden values found in
+     * class GoldenDoubleValues.
+     */
+    private static void generatesGoldenFormattedValuesClass() {
+
+        String fourWhiteSpaces    = "    ";
+        String eightWhiteSpaces   = "        ";
+
+        // Prints header without Copyright header.
+        System.out.println("/* This is a machine generated file - Please DO NOT EDIT !");
+        System.out.println(" * Change RoundingAndPropertyTest instead,");
+        System.out.println(" * and run with \"-gengold\" argument to regenerate (without copyright header).");
+        System.out.println(" */");
+        System.out.println();
+
+        System.out.println("/* This file contains the set of result Strings expected from calling inside");
+        System.out.println(" * RoundingAndPropertyTest the method NumberFormat.format() upon the set of");
+        System.out.println(" * double values provided in GoldenDoubleValues.java. It contains three arrays,");
+        System.out.println(" * each containing arrays of unicode values representing the expected string");
+        System.out.println(" * result when calling format() on the corresponding (i.e. same index) double");
+        System.out.println(" * value found in GoldenDoubleValues arrays :");
+        System.out.println(" * - DecimalDigitsLocalizedFormattedValues corresponds to DecimalLocalizationValues,");
+        System.out.println(" *   when using FullLocalizationTestLocale to format.");
+        System.out.println(" * - DecimalGoldenFormattedValues corresponds to DecimalGoldenValues, when used");
+        System.out.println(" *   in the decimal pattern case together with TestLocale.");
+        System.out.println(" * - CurrencyGoldenFormattedValues corresponds to CurrencyGoldenValues. when used");
+        System.out.println(" *   in the currency pattern case together with TestLocale.");
+        System.out.println(" * Please see documentation in RoundingAndPropertyTest.java for more details.");
+        System.out.println(" *");
+        System.out.println(" * This file generated by running RoundingAndPropertyTest with \"-gengold\" argument.");
+        System.out.println(" */");
+        System.out.println();
+
+        // Prints beginning of class GoldenFormattedValues.
+        System.out.println("class GoldenFormattedValues {");
+        System.out.println();
+        System.out.println(
+            fourWhiteSpaces +
+            "// The formatted values below were generated from golden values");
+        System.out.print(
+            fourWhiteSpaces +
+            "// listed in GoldenDoubleValues.java,");
+        System.out.println(" using the following jvm version :");
+        System.out.println(
+            fourWhiteSpaces + "//   " +
+            System.getProperty("java.vendor") +
+            " " +
+            System.getProperty("java.vm.name") +
+            " " +
+            System.getProperty("java.version"));
+        System.out.println(
+            fourWhiteSpaces +
+            "//   locale for golden double values : " + GoldenDoubleValues.TestLocale);
+        System.out.println(
+            fourWhiteSpaces +
+            "//   locale for testing digit localization : " + GoldenDoubleValues.FullLocalizationTestLocale);
+        System.out.println();
+
+        // Prints the expected results when digit localization happens
+        System.out.println(
+            fourWhiteSpaces +
+            "// The array of int[] unicode values storing the expected results");
+        System.out.print(
+            fourWhiteSpaces +
+            "// when experiencing full localization of digits");
+        System.out.println(" on DecimalLocalizationValues.");
+        System.out.println(
+            fourWhiteSpaces +
+            "static int[][] DecimalDigitsLocalizedFormattedValues = {");
+        NumberFormat df =
+            NumberFormat.getInstance(GoldenDoubleValues.FullLocalizationTestLocale);
+        for (int i = 0;
+             i < GoldenDoubleValues.DecimalLocalizationValues.length;
+             i++) {
+            double d = GoldenDoubleValues.DecimalLocalizationValues[i];
+            String formatted = df.format(d);
+            char[] decFmtChars = formatted.toCharArray();
+
+            System.out.print(eightWhiteSpaces + "{ ");
+            printUnicodeValuesArray(decFmtChars);
+            System.out.println(" },");
+        }
+        System.out.println(fourWhiteSpaces + "};");
+        System.out.println();
+
+        // Prints the golden expected results for the decimal pattern case
+        System.out.println(
+            fourWhiteSpaces +
+            "// The array of int[] unicode values storing the expected results");
+        System.out.print(
+            fourWhiteSpaces +
+            "// when calling Decimal.format(double)");
+        System.out.println(" on the decimal GoldenDoubleValues.");
+        System.out.println(
+            fourWhiteSpaces +
+            "static int[][] DecimalGoldenFormattedValues = {");
+        df = NumberFormat.getInstance(GoldenDoubleValues.TestLocale);
+        for (int i = 0;
+             i < GoldenDoubleValues.DecimalGoldenValues.length;
+             i++) {
+            double d = GoldenDoubleValues.DecimalGoldenValues[i];
+            String formatted = df.format(d);
+            char[] decFmtChars = formatted.toCharArray();
+
+            System.out.print(eightWhiteSpaces + "{ ");
+            printUnicodeValuesArray(decFmtChars);
+            System.out.println(" },");
+        }
+        System.out.println(fourWhiteSpaces + "};");
+        System.out.println();
+
+        // Prints the golden expected results for the currency pattern case
+        System.out.println(
+            fourWhiteSpaces +
+            "// The array of int[] unicode values storing the expected results");
+        System.out.print(
+            fourWhiteSpaces +
+            "// when calling Decimal.format(double)");
+        System.out.println(" on the currency GoldenDoubleValues.");
+        System.out.println(
+            fourWhiteSpaces +
+            "static int[][] CurrencyGoldenFormattedValues = {");
+        NumberFormat cf =
+            NumberFormat.getCurrencyInstance(GoldenDoubleValues.TestLocale);
+        for (int i = 0;
+             i < GoldenDoubleValues.CurrencyGoldenValues.length;
+             i++) {
+            double d = GoldenDoubleValues.CurrencyGoldenValues[i];
+            String formatted = cf.format(d);
+            char[] decFmtChars = formatted.toCharArray();
+
+            System.out.print(eightWhiteSpaces + "{ ");
+            printUnicodeValuesArray(decFmtChars);
+            System.out.println(" },");
+        }
+        System.out.println(fourWhiteSpaces + "};");
+        System.out.println();
+
+        // Prints end of GoldenFormattedValues class.
+        System.out.println("}");
+    }
+
+    private static int testLocalizationValues() {
+
+        DecimalFormat df = (DecimalFormat)
+            NumberFormat.getInstance(GoldenDoubleValues.FullLocalizationTestLocale);
+
+        double[] localizationValues = GoldenDoubleValues.DecimalLocalizationValues;
+        int size = localizationValues.length;
+        int successCounter = 0;
+        int failureCounter = 0;
+        for (int i = 0; i < size; i++) {
+
+            double d = localizationValues[i];
+            String formatted = df.format(d);
+
+            char[] expectedUnicodeArray =
+                getCharsFromUnicodeArray(
+                    GoldenFormattedValues.DecimalDigitsLocalizedFormattedValues[i]);
+            String expected = new String(expectedUnicodeArray);
+
+            if (!formatted.equals(expected)) {
+                failureCounter++;
+                System.out.println(
+                    "--- Localization error for value d = " + d +
+                    ". Exact value = " + new BigDecimal(d).toString() +
+                    ". Expected result = " + expected +
+                    ". Output result = " + formatted);
+            } else successCounter++;
+        }
+        System.out.println("Checked positively " + successCounter +
+                           " golden decimal values out of " + size +
+                           " tests. There were " + failureCounter +
+                           " format failure");
+
+        return failureCounter;
+    }
+
+    private static int testGoldenValues(java.text.DecimalFormat df,
+                                        java.text.DecimalFormat cf) {
+
+        double[] goldenDecimalValues = GoldenDoubleValues.DecimalGoldenValues;
+        int decimalSize = goldenDecimalValues.length;
+        int decimalSuccessCounter = 0;
+        int decimalFailureCounter = 0;
+        for (int i = 0; i < decimalSize; i++) {
+
+            double d = goldenDecimalValues[i];
+            String formatted = df.format(d);
+
+            char[] expectedUnicodeArray =
+                getCharsFromUnicodeArray(
+                    GoldenFormattedValues.DecimalGoldenFormattedValues[i]);
+            String expected = new String(expectedUnicodeArray);
+
+            if (!formatted.equals(expected)) {
+                decimalFailureCounter++;
+                System.out.println(
+                    "--- Error for golden value d = " + d +
+                    ". Exact value = " + new BigDecimal(d).toString() +
+                    ". Expected result = " + expected +
+                    ". Output result = " + formatted);
+            } else decimalSuccessCounter++;
+        }
+        System.out.println("Checked positively " + decimalSuccessCounter +
+                           " golden decimal values out of " + decimalSize +
+                           " tests. There were " + decimalFailureCounter +
+                           " format failure");
+
+        double[] goldenCurrencyValues = GoldenDoubleValues.CurrencyGoldenValues;
+        int currencySize = goldenCurrencyValues.length;
+        int currencySuccessCounter = 0;
+        int currencyFailureCounter = 0;
+        for (int i = 0; i < currencySize; i++) {
+            double d = goldenCurrencyValues[i];
+            String formatted = cf.format(d);
+
+            char[] expectedUnicodeArray =
+                getCharsFromUnicodeArray(
+                    GoldenFormattedValues.CurrencyGoldenFormattedValues[i]);
+            String expected = new String(expectedUnicodeArray);
+
+            if (!formatted.equals(expected)) {
+                currencyFailureCounter++;
+                System.out.println(
+                    "--- Error for golden value d = " + d +
+                    ". Exact value = " + new BigDecimal(d).toString() +
+                    ". Expected result = " + expected +
+                    ". Output result = " + formatted);
+            } else currencySuccessCounter++;
+        }
+        System.out.println("Checked positively " + currencySuccessCounter +
+                           " golden currency values out of " + currencySize +
+                           " tests. There were " + currencyFailureCounter +
+                           " format failure");
+
+        return (decimalFailureCounter + currencyFailureCounter);
+    }
+
+    // Checks that the two passed s1 and s2 string are equal, and prints
+    // out message in case of error.
+    private static boolean resultsEqual(String propertyName,
+                                        String s1,
+                                        String s2) {
+
+        boolean equality = s1.equals(s2);
+        if (!equality)
+            System.out.println(
+                "\n*** Error while reverting to default " +
+                propertyName + " property.\n" +
+                "    initial output = " + s1 +
+                ". reverted output = " + s2 + ".");
+        else System.out.println(" Test passed.");
+
+        return equality;
+
+    }
+
+    /* This methods checks the behaviour of the management of properties
+     * of a DecimalFormat instance that satisfies fast-path constraints.
+     *
+     * It does this by comparing the results of the format(double) output
+     * obtained from initial fast-path state with the output provided by
+     * the same instance that has been pushed and exercised outside
+     * fast-path rules and finally "reverted" to its initial fast-path state.
+     *
+     * The schema of actions is this :
+     *  - Call format(double) on a known DecimalFormat fast-path instance,
+     *    and store this result.
+     *  - Record the current state of a given property.
+     *  - Change the property to invalidate the fast-path state.
+     *  - Call again format(double) on the instance.
+     *  - Revert state of property to validate again fast-path context.
+     *  - Call format(double) again.
+     *  - Check that first and last call to format(double) provide same result
+     *  - Record failure if any.
+     *  - Do the same for another property with the same instance.
+     * So all the property changes are chained one after the other on only the
+     * same instance.
+     *
+     * Some properties that currently do not influence the fast-path state
+     * are also tested. This is not useful with current fast-path source
+     * but is here for testing the whole set of properties. This is the case
+     * for prefixes and suffixes, and parseBigDecimal properties.
+     */
+    private static int testSettersAndFastPath(DecimalFormat df,
+                                               boolean isCurrency) {
+
+        final double d1 = GoldenDoubleValues.PROPERTY_CHECK_POSITIVE_VALUE;
+        final double d2 = GoldenDoubleValues.PROPERTY_CHECK_NEGATIVE_VALUE;
+
+        int errors = 0;
+        boolean testSucceeded = false;
+        String firstFormatResult;
+        String secondFormatResult;
+        String propertyName;
+
+        // ---- positivePrefix property test ----
+        testSucceeded = false;
+        propertyName = "positivePrefix";
+        System.out.print("Checking " + propertyName + " property.");
+        String initialPrefix = df.getPositivePrefix();
+        firstFormatResult = df.format(d1);
+        df.setPositivePrefix("positivePrefix:");
+        df.format(d1);
+        df.setPositivePrefix(initialPrefix);
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        // ---- positiveSuffix property test ----
+        testSucceeded = false;
+        propertyName = "positiveSuffix";
+        System.out.print("Checking " + propertyName + " property.");
+        String initialSuffix = df.getPositiveSuffix();
+        firstFormatResult = df.format(d1);
+        df.setPositiveSuffix("positiveSuffix:");
+        df.format(d1);
+        df.setPositiveSuffix(initialSuffix);
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName,firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        // ---- negativePrefix property test ----
+        testSucceeded = false;
+        propertyName = "negativePrefix";
+        System.out.print("Checking " + propertyName + " property.");
+        initialPrefix = df.getNegativePrefix();
+        firstFormatResult = df.format(d1);
+        df.setNegativePrefix("negativePrefix:");
+        df.format(d1);
+        df.setNegativePrefix(initialPrefix);
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        // ---- negativeSuffix property test ----
+        testSucceeded = false;
+        propertyName = "negativeSuffix";
+        System.out.print("Checking " + propertyName + " property.");
+        initialSuffix = df.getNegativeSuffix();
+        firstFormatResult = df.format(d1);
+        df.setNegativeSuffix("negativeSuffix:");
+        df.format(d1);
+        df.setNegativeSuffix(initialSuffix);
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        // ---- multiplier property test ----
+        testSucceeded = false;
+        propertyName = "multiplier";
+        System.out.print("Checking " + propertyName + " property.");
+        int initialMultiplier = df.getMultiplier();
+        firstFormatResult = df.format(d1);
+        df.setMultiplier(10);
+        df.format(d1);
+        df.setMultiplier(initialMultiplier);
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        // ---- groupingUsed property test ----
+        testSucceeded = false;
+        propertyName = "groupingUsed";
+        System.out.print("Checking " + propertyName + " property.");
+        boolean initialGroupingUsed = df.isGroupingUsed();
+        firstFormatResult = df.format(d1);
+        df.setGroupingUsed(!initialGroupingUsed);
+        df.format(d1);
+        df.setGroupingUsed(initialGroupingUsed);
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        // ---- groupingSize property test ----
+        testSucceeded = false;
+        propertyName = "groupingSize";
+        System.out.print("Checking " + propertyName + " property.");
+        int initialGroupingSize = df.getGroupingSize();
+        firstFormatResult = df.format(d1);
+        df.setGroupingSize(initialGroupingSize + 1);
+        df.format(d1);
+        df.setGroupingSize(initialGroupingSize);
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        // ---- decimalSeparatorAlwaysShown property test ----
+        testSucceeded = false;
+        propertyName = "decimalSeparatorAlwaysShown";
+        System.out.print("Checking " + propertyName + " property.");
+        boolean initialDSShown = df.isDecimalSeparatorAlwaysShown();
+        firstFormatResult = df.format(d1);
+        df.setDecimalSeparatorAlwaysShown(!initialDSShown);
+        df.format(d1);
+        df.setDecimalSeparatorAlwaysShown(initialDSShown);
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        // ---- parseBigDecimal property test ----
+        testSucceeded = false;
+        propertyName = "parseBigDecimal";
+        System.out.print("Checking " + propertyName + " property.");
+        boolean initialParseBigdecimal = df.isParseBigDecimal();
+        firstFormatResult = df.format(d1);
+        df.setParseBigDecimal(!initialParseBigdecimal);
+        df.format(d1);
+        df.setParseBigDecimal(initialParseBigdecimal);
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        // ---- maximumIntegerDigits property test ----
+        testSucceeded = false;
+        propertyName = "maximumIntegerDigits";
+        System.out.print("Checking " + propertyName + " property.");
+        int initialMaxIDs = df.getMaximumIntegerDigits();
+        firstFormatResult = df.format(d1);
+        df.setMaximumIntegerDigits(8);
+        df.format(d1);
+        df.setMaximumIntegerDigits(initialMaxIDs);
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        // ---- minimumIntegerDigits property test ----
+        testSucceeded = false;
+        propertyName = "minimumIntegerDigits";
+        System.out.print("Checking " + propertyName + " property.");
+        int initialMinIDs = df.getMinimumIntegerDigits();
+        firstFormatResult = df.format(d1);
+        df.setMinimumIntegerDigits(2);
+        df.format(d1);
+        df.setMinimumIntegerDigits(initialMinIDs);
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        // ---- maximumFractionDigits property test ----
+        testSucceeded = false;
+        propertyName = "maximumFractionDigits";
+        System.out.print("Checking " + propertyName + " property.");
+        firstFormatResult = df.format(d1);
+        df.setMaximumFractionDigits(8);
+        df.format(d1);
+        if (isCurrency) {
+            df.setMinimumFractionDigits(2);
+            df.setMaximumFractionDigits(2);
+        } else {
+            df.setMinimumFractionDigits(0);
+            df.setMaximumFractionDigits(3);
+        }
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        // ---- minimumFractionDigits property test ----
+        testSucceeded = false;
+        propertyName = "minimumFractionDigits";
+        System.out.print("Checking " + propertyName + " property.");
+        firstFormatResult = df.format(d1);
+        df.setMinimumFractionDigits(1);
+        df.format(d1);
+        if (isCurrency) {
+            df.setMinimumFractionDigits(2);
+            df.setMaximumFractionDigits(2);
+        } else {
+            df.setMinimumFractionDigits(0);
+            df.setMaximumFractionDigits(3);
+        }
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        // ---- currency property test ----
+        testSucceeded = false;
+        propertyName = "currency";
+        System.out.print("Checking " + propertyName + " property.");
+        Currency initialCurrency = df.getCurrency();
+        Currency japanCur = java.util.Currency.getInstance(Locale.JAPAN);
+        firstFormatResult = df.format(d1);
+        df.setCurrency(japanCur);
+        df.format(d1);
+        df.setCurrency(initialCurrency);
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        // ---- roundingMode property test ----
+        testSucceeded = false;
+        propertyName = "roundingMode";
+        System.out.print("Checking " + propertyName + " property.");
+        RoundingMode initialRMode = df.getRoundingMode();
+        firstFormatResult = df.format(d1);
+        df.setRoundingMode(RoundingMode.HALF_UP);
+        df.format(d1);
+        df.setRoundingMode(RoundingMode.HALF_EVEN);
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        // ---- decimalFormatSymbols property test ----
+        testSucceeded = false;
+        propertyName = "decimalFormatSymbols";
+        System.out.print("Checking " + propertyName + " property.");
+        DecimalFormatSymbols initialDecimalFormatSymbols = df.getDecimalFormatSymbols();
+        firstFormatResult = df.format(d1);
+        Locale bizarreLocale = new Locale("fr", "FR");
+        DecimalFormatSymbols unusualSymbols = new DecimalFormatSymbols(bizarreLocale);
+        unusualSymbols.setDecimalSeparator('@');
+        unusualSymbols.setGroupingSeparator('|');
+        df.setDecimalFormatSymbols(unusualSymbols);
+        df.format(d1);
+        df.setDecimalFormatSymbols(initialDecimalFormatSymbols);
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        testSucceeded = false;
+        System.out.print("Checking " + propertyName + " property.");
+        initialDecimalFormatSymbols = df.getDecimalFormatSymbols();
+        firstFormatResult = df.format(d1);
+        Locale japanLocale = Locale.JAPAN;
+        unusualSymbols = new DecimalFormatSymbols(japanLocale);
+        unusualSymbols.setDecimalSeparator('9');
+        unusualSymbols.setGroupingSeparator('0');
+        df.setDecimalFormatSymbols(unusualSymbols);
+        df.format(d1);
+        df.setDecimalFormatSymbols(initialDecimalFormatSymbols);
+        secondFormatResult = df.format(d1);
+        testSucceeded =
+            resultsEqual(propertyName, firstFormatResult, secondFormatResult);
+        if (!testSucceeded)
+            errors++;
+
+        return errors;
+    }
+
+    // Main for RoundingAndPropertyTest. We test first the golden values,
+    // and then the property setters and getters.
+    public static void main(String[] args) {
+
+        if ((args.length >= 1) &&
+            (args[0].equals("-gengold")))
+            generatesGoldenFormattedValuesClass();
+        else {
+            System.out.println("\nChecking correctness of formatting with digit localization.");
+            System.out.println("=============================================================");
+            int localizationErrors = testLocalizationValues();
+            if (localizationErrors != 0)
+                System.out.println("*** Failure in localization tests : " +
+                                   localizationErrors + " errors detected ");
+            else System.out.println(" Tests for full localization of digits all passed.");
+
+            DecimalFormat df = (DecimalFormat)
+                NumberFormat.getInstance(GoldenDoubleValues.TestLocale);
+            DecimalFormat cf = (DecimalFormat)
+                NumberFormat.getCurrencyInstance(GoldenDoubleValues.TestLocale);
+
+            System.out.println("\nChecking correctness of formating for golden values.");
+            System.out.println("=============================================================");
+            int goldenValuesErrors = testGoldenValues(df,cf);
+            if (goldenValuesErrors != 0)
+                System.out.println("*** Failure in goldenValues tests : " +
+                                   goldenValuesErrors + " errors detected ");
+            else System.out.println(" Tests for golden values all passed.");
+
+            System.out.println("\nChecking behavior of property changes for decimal case.");
+            System.out.println("=============================================================");
+            int decimalTestsErrors = testSettersAndFastPath(df, false);
+            if (decimalTestsErrors != 0)
+                System.out.println("*** Failure in decimal property changes tests : " +
+                                   decimalTestsErrors + " errors detected ");
+            else System.out.println(" Tests for decimal property changes all passed.");
+
+            System.out.println("\nChecking behavior of property changes for currency case.");
+            System.out.println("=============================================================");
+            int currencyTestsErrors = testSettersAndFastPath(cf, true);
+            if (currencyTestsErrors != 0)
+                System.out.println("*** Failure in currency property changes tests : " +
+                                   currencyTestsErrors + " errors detected ");
+            else System.out.println(" Tests for currency property chamges all passed.");
+
+            if ((localizationErrors > 0) ||
+                (goldenValuesErrors > 0) ||
+                (decimalTestsErrors > 0) ||
+                (currencyTestsErrors > 0))
+                throw new RuntimeException(
+                    "Failed with " +
+                    (localizationErrors + goldenValuesErrors +
+                     decimalTestsErrors + currencyTestsErrors) +
+                    " error(s).");
+        }
+    }
+}