/*
 *******************************************************************************
 * Copyright (C) 1996-2013, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.text;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.text.ChoiceFormat;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import com.ibm.icu.impl.ICUConfig;
import com.ibm.icu.impl.PatternProps;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.math.BigDecimal;
import com.ibm.icu.math.MathContext;
import com.ibm.icu.text.PluralRules.FixedDecimal;
import com.ibm.icu.util.Currency;
import com.ibm.icu.util.CurrencyAmount;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.ULocale.Category;

/**
 * {@icuenhanced java.text.DecimalFormat}.{@icu _usage_}
 *
 * <code>DecimalFormat</code> is a concrete subclass of {@link NumberFormat} that formats
 * decimal numbers. It has a variety of features designed to make it possible to parse and
 * format numbers in any locale, including support for Western, Arabic, or Indic digits.
 * It also supports different flavors of numbers, including integers ("123"), fixed-point
 * numbers ("123.4"), scientific notation ("1.23E4"), percentages ("12%"), and currency
 * amounts ("$123.00", "USD123.00", "123.00 US dollars").  All of these flavors can be
 * easily localized.
 *
 * <p>To obtain a {@link NumberFormat} for a specific locale (including the default
 * locale) call one of <code>NumberFormat</code>'s factory methods such as {@link
 * NumberFormat#getInstance}. Do not call the <code>DecimalFormat</code> constructors
 * directly, unless you know what you are doing, since the {@link NumberFormat} factory
 * methods may return subclasses other than <code>DecimalFormat</code>. If you need to
 * customize the format object, do something like this:
 *
 * <blockquote><pre>
 * NumberFormat f = NumberFormat.getInstance(loc);
 * if (f instanceof DecimalFormat) {
 *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
 * }</pre></blockquote>
 *
 * <p><strong>Example Usage</strong>
 *
 * Print out a number using the localized number, currency, and percent
 * format for each locale.
 *
 * <blockquote><pre>
 * Locale[] locales = NumberFormat.getAvailableLocales();
 * double myNumber = -1234.56;
 * NumberFormat format;
 * for (int j=0; j<3; ++j) {
 *     System.out.println("FORMAT");
 *     for (int i = 0; i < locales.length; ++i) {
 *         if (locales[i].getCountry().length() == 0) {
 *            // Skip language-only locales
 *            continue;
 *         }
 *         System.out.print(locales[i].getDisplayName());
 *         switch (j) {
 *         case 0:
 *             format = NumberFormat.getInstance(locales[i]); break;
 *         case 1:
 *             format = NumberFormat.getCurrencyInstance(locales[i]); break;
 *         default:
 *             format = NumberFormat.getPercentInstance(locales[i]); break;
 *         }
 *         try {
 *             // Assume format is a DecimalFormat
 *             System.out.print(": " + ((DecimalFormat) format).toPattern()
 *                              + " -> " + form.format(myNumber));
 *         } catch (Exception e) {}
 *         try {
 *             System.out.println(" -> " + format.parse(form.format(myNumber)));
 *         } catch (ParseException e) {}
 *     }
 * }</pre></blockquote>
 *
 * <p>Another example use getInstance(style).<br/>
 * Print out a number using the localized number, currency, percent,
 * scientific, integer, iso currency, and plural currency format for each locale.
 *
 * <blockquote><pre>
 * ULocale locale = new ULocale("en_US");
 * double myNumber = 1234.56;
 * for (int j=NumberFormat.NUMBERSTYLE; j<=NumberFormat.PLURALCURRENCYSTYLE; ++j) {
 *     NumberFormat format = NumberFormat.getInstance(locale, j);
 *     try {
 *         // Assume format is a DecimalFormat
 *         System.out.print(": " + ((DecimalFormat) format).toPattern()
 *                          + " -> " + form.format(myNumber));
 *     } catch (Exception e) {}
 *     try {
 *         System.out.println(" -> " + format.parse(form.format(myNumber)));
 *     } catch (ParseException e) {}
 * }</pre></blockquote>
 *
 * <h4>Patterns</h4>
 *
 * <p>A <code>DecimalFormat</code> consists of a <em>pattern</em> and a set of
 * <em>symbols</em>.  The pattern may be set directly using {@link #applyPattern}, or
 * indirectly using other API methods which manipulate aspects of the pattern, such as the
 * minimum number of integer digits.  The symbols are stored in a {@link
 * DecimalFormatSymbols} object.  When using the {@link NumberFormat} factory methods, the
 * pattern and symbols are read from ICU's locale data.
 *
 * <h4>Special Pattern Characters</h4>
 *
 * <p>Many characters in a pattern are taken literally; they are matched during parsing
 * and output unchanged during formatting.  Special characters, on the other hand, stand
 * for other characters, strings, or classes of characters.  For example, the '#'
 * character is replaced by a localized digit.  Often the replacement character is the
 * same as the pattern character; in the U.S. locale, the ',' grouping character is
 * replaced by ','.  However, the replacement is still happening, and if the symbols are
 * modified, the grouping character changes.  Some special characters affect the behavior
 * of the formatter by their presence; for example, if the percent character is seen, then
 * the value is multiplied by 100 before being displayed.
 *
 * <p>To insert a special character in a pattern as a literal, that is, without any
 * special meaning, the character must be quoted.  There are some exceptions to this which
 * are noted below.
 *
 * <p>The characters listed here are used in non-localized patterns.  Localized patterns
 * use the corresponding characters taken from this formatter's {@link
 * DecimalFormatSymbols} object instead, and these characters lose their special status.
 * Two exceptions are the currency sign and quote, which are not localized.
 *
 * <blockquote>
 * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
 *  location, localized, and meaning.">
 *   <tr bgcolor="#ccccff">
 *     <th align=left>Symbol
 *     <th align=left>Location
 *     <th align=left>Localized?
 *     <th align=left>Meaning
 *   <tr valign=top>
 *     <td><code>0</code>
 *     <td>Number
 *     <td>Yes
 *     <td>Digit
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>1-9</code>
 *     <td>Number
 *     <td>Yes
 *     <td>'1' through '9' indicate rounding.
 *   <tr valign=top>
 *     <td><code>@</code>
 *     <td>Number
 *     <td>No
 *     <td>Significant digit
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>#</code>
 *     <td>Number
 *     <td>Yes
 *     <td>Digit, zero shows as absent
 *   <tr valign=top>
 *     <td><code>.</code>
 *     <td>Number
 *     <td>Yes
 *     <td>Decimal separator or monetary decimal separator
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>-</code>
 *     <td>Number
 *     <td>Yes
 *     <td>Minus sign
 *   <tr valign=top>
 *     <td><code>,</code>
 *     <td>Number
 *     <td>Yes
 *     <td>Grouping separator
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>E</code>
 *     <td>Number
 *     <td>Yes
 *     <td>Separates mantissa and exponent in scientific notation.
 *         <em>Need not be quoted in prefix or suffix.</em>
 *   <tr valign=top>
 *     <td><code>+</code>
 *     <td>Exponent
 *     <td>Yes
 *     <td>Prefix positive exponents with localized plus sign.
 *         <em>Need not be quoted in prefix or suffix.</em>
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>;</code>
 *     <td>Subpattern boundary
 *     <td>Yes
 *     <td>Separates positive and negative subpatterns
 *   <tr valign=top>
 *     <td><code>%</code>
 *     <td>Prefix or suffix
 *     <td>Yes
 *     <td>Multiply by 100 and show as percentage
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>&#92;u2030</code>
 *     <td>Prefix or suffix
 *     <td>Yes
 *     <td>Multiply by 1000 and show as per mille
 *   <tr valign=top>
 *     <td><code>&#164;</code> (<code>&#92;u00A4</code>)
 *     <td>Prefix or suffix
 *     <td>No
 *     <td>Currency sign, replaced by currency symbol.  If
 *         doubled, replaced by international currency symbol.
 *         If tripled, replaced by currency plural names, for example,
 *         "US dollar" or "US dollars" for America.
 *         If present in a pattern, the monetary decimal separator
 *         is used instead of the decimal separator.
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>'</code>
 *     <td>Prefix or suffix
 *     <td>No
 *     <td>Used to quote special characters in a prefix or suffix,
 *         for example, <code>"'#'#"</code> formats 123 to
 *         <code>"#123"</code>.  To create a single quote
 *         itself, use two in a row: <code>"# o''clock"</code>.
 *   <tr valign=top>
 *     <td><code>*</code>
 *     <td>Prefix or suffix boundary
 *     <td>Yes
 *     <td>Pad escape, precedes pad character
 * </table>
 * </blockquote>
 *
 * <p>A <code>DecimalFormat</code> pattern contains a postive and negative subpattern, for
 * example, "#,##0.00;(#,##0.00)".  Each subpattern has a prefix, a numeric part, and a
 * suffix.  If there is no explicit negative subpattern, the negative subpattern is the
 * localized minus sign prefixed to the positive subpattern. That is, "0.00" alone is
 * equivalent to "0.00;-0.00".  If there is an explicit negative subpattern, it serves
 * only to specify the negative prefix and suffix; the number of digits, minimal digits,
 * and other characteristics are ignored in the negative subpattern. That means that
 * "#,##0.0#;(#)" has precisely the same result as "#,##0.0#;(#,##0.0#)".
 *
 * <p>The prefixes, suffixes, and various symbols used for infinity, digits, thousands
 * separators, decimal separators, etc. may be set to arbitrary values, and they will
 * appear properly during formatting.  However, care must be taken that the symbols and
 * strings do not conflict, or parsing will be unreliable.  For example, either the
 * positive and negative prefixes or the suffixes must be distinct for {@link #parse} to
 * be able to distinguish positive from negative values.  Another example is that the
 * decimal separator and thousands separator should be distinct characters, or parsing
 * will be impossible.
 *
 * <p>The <em>grouping separator</em> is a character that separates clusters of integer
 * digits to make large numbers more legible.  It commonly used for thousands, but in some
 * locales it separates ten-thousands.  The <em>grouping size</em> is the number of digits
 * between the grouping separators, such as 3 for "100,000,000" or 4 for "1 0000
 * 0000". There are actually two different grouping sizes: One used for the least
 * significant integer digits, the <em>primary grouping size</em>, and one used for all
 * others, the <em>secondary grouping size</em>.  In most locales these are the same, but
 * sometimes they are different. For example, if the primary grouping interval is 3, and
 * the secondary is 2, then this corresponds to the pattern "#,##,##0", and the number
 * 123456789 is formatted as "12,34,56,789".  If a pattern contains multiple grouping
 * separators, the interval between the last one and the end of the integer defines the
 * primary grouping size, and the interval between the last two defines the secondary
 * grouping size. All others are ignored, so "#,##,###,####" == "###,###,####" ==
 * "##,#,###,####".
 *
 * <p>Illegal patterns, such as "#.#.#" or "#.###,###", will cause
 * <code>DecimalFormat</code> to throw an {@link IllegalArgumentException} with a message
 * that describes the problem.
 *
 * <h4>Pattern BNF</h4>
 *
 * <pre>
 * pattern    := subpattern (';' subpattern)?
 * subpattern := prefix? number exponent? suffix?
 * number     := (integer ('.' fraction)?) | sigDigits
 * prefix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
 * suffix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
 * integer    := '#'* '0'* '0'
 * fraction   := '0'* '#'*
 * sigDigits  := '#'* '@' '@'* '#'*
 * exponent   := 'E' '+'? '0'* '0'
 * padSpec    := '*' padChar
 * padChar    := '&#92;u0000'..'&#92;uFFFD' - quote
 * &#32;
 * Notation:
 *   X*       0 or more instances of X
 *   X?       0 or 1 instances of X
 *   X|Y      either X or Y
 *   C..D     any character from C up to D, inclusive
 *   S-T      characters in S, except those in T
 * </pre>
 * The first subpattern is for positive numbers. The second (optional)
 * subpattern is for negative numbers.
 *
 * <p>Not indicated in the BNF syntax above:
 *
 * <ul>
 *
 * <li>The grouping separator ',' can occur inside the integer and sigDigits
 * elements, between any two pattern characters of that element, as long as the integer or
 * sigDigits element is not followed by the exponent element.
 *
 * <li>Two grouping intervals are recognized: That between the decimal point and the first
 * grouping symbol, and that between the first and second grouping symbols. These
 * intervals are identical in most locales, but in some locales they differ. For example,
 * the pattern &quot;#,##,###&quot; formats the number 123456789 as
 * &quot;12,34,56,789&quot;.
 *
 * <li>The pad specifier <code>padSpec</code> may appear before the prefix, after the
 * prefix, before the suffix, after the suffix, or not at all.
 *
 * <li>In place of '0', the digits '1' through '9' may be used to indicate a rounding
 * increment.
 *
 * </ul>
 *
 * <h4>Parsing</h4>
 *
 * <p><code>DecimalFormat</code> parses all Unicode characters that represent decimal
 * digits, as defined by {@link UCharacter#digit}.  In addition,
 * <code>DecimalFormat</code> also recognizes as digits the ten consecutive characters
 * starting with the localized zero digit defined in the {@link DecimalFormatSymbols}
 * object.  During formatting, the {@link DecimalFormatSymbols}-based digits are output.
 *
 * <p>During parsing, grouping separators are ignored.
 *
 * <p>For currency parsing, the formatter is able to parse every currency style formats no
 * matter which style the formatter is constructed with.  For example, a formatter
 * instance gotten from NumberFormat.getInstance(ULocale, NumberFormat.CURRENCYSTYLE) can
 * parse formats such as "USD1.00" and "3.00 US dollars".
 *
 * <p>If {@link #parse(String, ParsePosition)} fails to parse a string, it returns
 * <code>null</code> and leaves the parse position unchanged.  The convenience method
 * {@link #parse(String)} indicates parse failure by throwing a {@link
 * java.text.ParseException}.
 *
 * <p>Parsing an extremely large or small absolute value (such as 1.0E10000 or 1.0E-10000)
 * requires huge memory allocation for representing the parsed number. Such input may expose
 * a risk of DoS attacks. To prevent huge memory allocation triggered by such inputs,
 * <code>DecimalFormat</code> internally limits of maximum decimal digits to be 1000. Thus,
 * an input string resulting more than 1000 digits in plain decimal representation (non-exponent)
 * will be treated as either overflow (positive/negative infinite) or underflow (+0.0/-0.0).
 *
 * <h4>Formatting</h4>
 *
 * <p>Formatting is guided by several parameters, all of which can be specified either
 * using a pattern or using the API.  The following description applies to formats that do
 * not use <a href="#sci">scientific notation</a> or <a href="#sigdig">significant
 * digits</a>.
 *
 * <ul><li>If the number of actual integer digits exceeds the <em>maximum integer
 * digits</em>, then only the least significant digits are shown.  For example, 1997 is
 * formatted as "97" if the maximum integer digits is set to 2.
 *
 * <li>If the number of actual integer digits is less than the <em>minimum integer
 * digits</em>, then leading zeros are added.  For example, 1997 is formatted as "01997"
 * if the minimum integer digits is set to 5.
 *
 * <li>If the number of actual fraction digits exceeds the <em>maximum fraction
 * digits</em>, then half-even rounding it performed to the maximum fraction digits.  For
 * example, 0.125 is formatted as "0.12" if the maximum fraction digits is 2.  This
 * behavior can be changed by specifying a rounding increment and a rounding mode.
 *
 * <li>If the number of actual fraction digits is less than the <em>minimum fraction
 * digits</em>, then trailing zeros are added.  For example, 0.125 is formatted as
 * "0.1250" if the mimimum fraction digits is set to 4.
 *
 * <li>Trailing fractional zeros are not displayed if they occur <em>j</em> positions
 * after the decimal, where <em>j</em> is less than the maximum fraction digits. For
 * example, 0.10004 is formatted as "0.1" if the maximum fraction digits is four or less.
 * </ul>
 *
 * <p><strong>Special Values</strong>
 *
 * <p><code>NaN</code> is represented as a single character, typically
 * <code>&#92;uFFFD</code>.  This character is determined by the {@link
 * DecimalFormatSymbols} object.  This is the only value for which the prefixes and
 * suffixes are not used.
 *
 * <p>Infinity is represented as a single character, typically <code>&#92;u221E</code>,
 * with the positive or negative prefixes and suffixes applied.  The infinity character is
 * determined by the {@link DecimalFormatSymbols} object.
 *
 * <a name="sci"><h4>Scientific Notation</h4></a>
 *
 * <p>Numbers in scientific notation are expressed as the product of a mantissa and a
 * power of ten, for example, 1234 can be expressed as 1.234 x 10<sup>3</sup>. The
 * mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0),
 * but it need not be.  <code>DecimalFormat</code> supports arbitrary mantissas.
 * <code>DecimalFormat</code> can be instructed to use scientific notation through the API
 * or through the pattern.  In a pattern, the exponent character immediately followed by
 * one or more digit characters indicates scientific notation.  Example: "0.###E0" formats
 * the number 1234 as "1.234E3".
 *
 * <ul>
 *
 * <li>The number of digit characters after the exponent character gives the minimum
 * exponent digit count.  There is no maximum.  Negative exponents are formatted using the
 * localized minus sign, <em>not</em> the prefix and suffix from the pattern.  This allows
 * patterns such as "0.###E0 m/s".  To prefix positive exponents with a localized plus
 * sign, specify '+' between the exponent and the digits: "0.###E+0" will produce formats
 * "1E+1", "1E+0", "1E-1", etc.  (In localized patterns, use the localized plus sign
 * rather than '+'.)
 *
 * <li>The minimum number of integer digits is achieved by adjusting the exponent.
 * Example: 0.00123 formatted with "00.###E0" yields "12.3E-4".  This only happens if
 * there is no maximum number of integer digits.  If there is a maximum, then the minimum
 * number of integer digits is fixed at one.
 *
 * <li>The maximum number of integer digits, if present, specifies the exponent grouping.
 * The most common use of this is to generate <em>engineering notation</em>, in which the
 * exponent is a multiple of three, e.g., "##0.###E0".  The number 12345 is formatted
 * using "##0.####E0" as "12.345E3".
 *
 * <li>When using scientific notation, the formatter controls the digit counts using
 * significant digits logic.  The maximum number of significant digits limits the total
 * number of integer and fraction digits that will be shown in the mantissa; it does not
 * affect parsing.  For example, 12345 formatted with "##0.##E0" is "12.3E3".  See the
 * section on significant digits for more details.
 *
 * <li>The number of significant digits shown is determined as follows: If
 * areSignificantDigitsUsed() returns false, then the minimum number of significant digits
 * shown is one, and the maximum number of significant digits shown is the sum of the
 * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is unaffected by the
 * maximum integer digits.  If this sum is zero, then all significant digits are shown.
 * If areSignificantDigitsUsed() returns true, then the significant digit counts are
 * specified by getMinimumSignificantDigits() and getMaximumSignificantDigits().  In this
 * case, the number of integer digits is fixed at one, and there is no exponent grouping.
 *
 * <li>Exponential patterns may not contain grouping separators.
 *
 * </ul>
 *
 * <a name="sigdig"><h4>Significant Digits</h4></a>
 *
 * <code>DecimalFormat</code> has two ways of controlling how many digits are shows: (a)
 * significant digits counts, or (b) integer and fraction digit counts.  Integer and
 * fraction digit counts are described above.  When a formatter is using significant
 * digits counts, the number of integer and fraction digits is not specified directly, and
 * the formatter settings for these counts are ignored.  Instead, the formatter uses
 * however many integer and fraction digits are required to display the specified number
 * of significant digits.  Examples:
 *
 * <blockquote>
 * <table border=0 cellspacing=3 cellpadding=0>
 *   <tr bgcolor="#ccccff">
 *     <th align=left>Pattern
 *     <th align=left>Minimum significant digits
 *     <th align=left>Maximum significant digits
 *     <th align=left>Number
 *     <th align=left>Output of format()
 *   <tr valign=top>
 *     <td><code>@@@</code>
 *     <td>3
 *     <td>3
 *     <td>12345
 *     <td><code>12300</code>
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>@@@</code>
 *     <td>3
 *     <td>3
 *     <td>0.12345
 *     <td><code>0.123</code>
 *   <tr valign=top>
 *     <td><code>@@##</code>
 *     <td>2
 *     <td>4
 *     <td>3.14159
 *     <td><code>3.142</code>
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>@@##</code>
 *     <td>2
 *     <td>4
 *     <td>1.23004
 *     <td><code>1.23</code>
 * </table>
 * </blockquote>
 *
 * <ul>
 *
 * <li>Significant digit counts may be expressed using patterns that specify a minimum and
 * maximum number of significant digits.  These are indicated by the <code>'@'</code> and
 * <code>'#'</code> characters.  The minimum number of significant digits is the number of
 * <code>'@'</code> characters.  The maximum number of significant digits is the number of
 * <code>'@'</code> characters plus the number of <code>'#'</code> characters following on
 * the right.  For example, the pattern <code>"@@@"</code> indicates exactly 3 significant
 * digits.  The pattern <code>"@##"</code> indicates from 1 to 3 significant digits.
 * Trailing zero digits to the right of the decimal separator are suppressed after the
 * minimum number of significant digits have been shown.  For example, the pattern
 * <code>"@##"</code> formats the number 0.1203 as <code>"0.12"</code>.
 *
 * <li>If a pattern uses significant digits, it may not contain a decimal separator, nor
 * the <code>'0'</code> pattern character.  Patterns such as <code>"@00"</code> or
 * <code>"@.###"</code> are disallowed.
 *
 * <li>Any number of <code>'#'</code> characters may be prepended to the left of the
 * leftmost <code>'@'</code> character.  These have no effect on the minimum and maximum
 * significant digits counts, but may be used to position grouping separators.  For
 * example, <code>"#,#@#"</code> indicates a minimum of one significant digits, a maximum
 * of two significant digits, and a grouping size of three.
 *
 * <li>In order to enable significant digits formatting, use a pattern containing the
 * <code>'@'</code> pattern character.  Alternatively, call {@link
 * #setSignificantDigitsUsed setSignificantDigitsUsed(true)}.
 *
 * <li>In order to disable significant digits formatting, use a pattern that does not
 * contain the <code>'@'</code> pattern character. Alternatively, call {@link
 * #setSignificantDigitsUsed setSignificantDigitsUsed(false)}.
 *
 * <li>The number of significant digits has no effect on parsing.
 *
 * <li>Significant digits may be used together with exponential notation. Such patterns
 * are equivalent to a normal exponential pattern with a minimum and maximum integer digit
 * count of one, a minimum fraction digit count of <code>getMinimumSignificantDigits() -
 * 1</code>, and a maximum fraction digit count of <code>getMaximumSignificantDigits() -
 * 1</code>. For example, the pattern <code>"@@###E0"</code> is equivalent to
 * <code>"0.0###E0"</code>.
 *
 * <li>If signficant digits are in use, then the integer and fraction digit counts, as set
 * via the API, are ignored.  If significant digits are not in use, then the signficant
 * digit counts, as set via the API, are ignored.
 *
 * </ul>
 *
 * <h4>Padding</h4>
 *
 * <p><code>DecimalFormat</code> supports padding the result of {@link #format} to a
 * specific width.  Padding may be specified either through the API or through the pattern
 * syntax.  In a pattern the pad escape character, followed by a single pad character,
 * causes padding to be parsed and formatted.  The pad escape character is '*' in
 * unlocalized patterns, and can be localized using {@link
 * DecimalFormatSymbols#setPadEscape}.  For example, <code>"$*x#,##0.00"</code> formats
 * 123 to <code>"$xx123.00"</code>, and 1234 to <code>"$1,234.00"</code>.
 *
 * <ul>
 *
 * <li>When padding is in effect, the width of the positive subpattern, including prefix
 * and suffix, determines the format width.  For example, in the pattern <code>"* #0
 * o''clock"</code>, the format width is 10.
 *
 * <li>The width is counted in 16-bit code units (Java <code>char</code>s).
 *
 * <li>Some parameters which usually do not matter have meaning when padding is used,
 * because the pattern width is significant with padding.  In the pattern "*
 * ##,##,#,##0.##", the format width is 14.  The initial characters "##,##," do not affect
 * the grouping size or maximum integer digits, but they do affect the format width.
 *
 * <li>Padding may be inserted at one of four locations: before the prefix, after the
 * prefix, before the suffix, or after the suffix.  If padding is specified in any other
 * location, {@link #applyPattern} throws an {@link IllegalArgumentException}.  If there
 * is no prefix, before the prefix and after the prefix are equivalent, likewise for the
 * suffix.
 *
 * <li>When specified in a pattern, the 16-bit <code>char</code> immediately following the
 * pad escape is the pad character. This may be any character, including a special pattern
 * character. That is, the pad escape <em>escapes</em> the following character. If there
 * is no character after the pad escape, then the pattern is illegal.
 *
 * </ul>
 *
 * <p>
 * <strong>Rounding</strong>
 *
 * <p><code>DecimalFormat</code> supports rounding to a specific increment.  For example,
 * 1230 rounded to the nearest 50 is 1250.  1.234 rounded to the nearest 0.65 is 1.3.  The
 * rounding increment may be specified through the API or in a pattern.  To specify a
 * rounding increment in a pattern, include the increment in the pattern itself.  "#,#50"
 * specifies a rounding increment of 50.  "#,##0.05" specifies a rounding increment of
 * 0.05.
 *
 * <ul>
 *
 * <li>Rounding only affects the string produced by formatting.  It does not affect
 * parsing or change any numerical values.
 *
 * <li>A <em>rounding mode</em> determines how values are rounded; see the {@link
 * com.ibm.icu.math.BigDecimal} documentation for a description of the modes.  Rounding
 * increments specified in patterns use the default mode, {@link
 * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN}.
 *
 * <li>Some locales use rounding in their currency formats to reflect the smallest
 * currency denomination.
 *
 * <li>In a pattern, digits '1' through '9' specify rounding, but otherwise behave
 * identically to digit '0'.
 *
 * </ul>
 *
 * <h4>Synchronization</h4>
 *
 * <p><code>DecimalFormat</code> objects are not synchronized.  Multiple threads should
 * not access one formatter concurrently.
 *
 * @see          java.text.Format
 * @see          NumberFormat
 * @author       Mark Davis
 * @author       Alan Liu
 * @stable ICU 2.0
 */
public class DecimalFormat extends NumberFormat {

    /**
     * Creates a DecimalFormat using the default pattern and symbols for the default
     * <code>FORMAT</code> locale. This is a convenient way to obtain a DecimalFormat when
     * internationalization is not the main concern.
     *
     * <p>To obtain standard formats for a given locale, use the factory methods on
     * NumberFormat such as getNumberInstance.  These factories will return the most
     * appropriate sub-class of NumberFormat for a given locale.
     *
     * @see NumberFormat#getInstance
     * @see NumberFormat#getNumberInstance
     * @see NumberFormat#getCurrencyInstance
     * @see NumberFormat#getPercentInstance
     * @see Category#FORMAT
     * @stable ICU 2.0
     */
    public DecimalFormat() {
        ULocale def = ULocale.getDefault(Category.FORMAT);
        String pattern = getPattern(def, 0);
        // Always applyPattern after the symbols are set
        this.symbols = new DecimalFormatSymbols(def);
        setCurrency(Currency.getInstance(def));
        applyPatternWithoutExpandAffix(pattern, false);
        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
            currencyPluralInfo = new CurrencyPluralInfo(def);
            // the exact pattern is not known until the plural count is known.
            // so, no need to expand affix now.
        } else {
            expandAffixAdjustWidth(null);
        }
    }

    /**
     * Creates a DecimalFormat from the given pattern and the symbols for the default
     * <code>FORMAT</code> locale. This is a convenient way to obtain a DecimalFormat when
     * internationalization is not the main concern.
     *
     * <p>To obtain standard formats for a given locale, use the factory methods on
     * NumberFormat such as getNumberInstance.  These factories will return the most
     * appropriate sub-class of NumberFormat for a given locale.
     *
     * @param pattern A non-localized pattern string.
     * @throws IllegalArgumentException if the given pattern is invalid.
     * @see NumberFormat#getInstance
     * @see NumberFormat#getNumberInstance
     * @see NumberFormat#getCurrencyInstance
     * @see NumberFormat#getPercentInstance
     * @see Category#FORMAT
     * @stable ICU 2.0
     */
    public DecimalFormat(String pattern) {
        // Always applyPattern after the symbols are set
        ULocale def = ULocale.getDefault(Category.FORMAT);
        this.symbols = new DecimalFormatSymbols(def);
        setCurrency(Currency.getInstance(def));
        applyPatternWithoutExpandAffix(pattern, false);
        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
            currencyPluralInfo = new CurrencyPluralInfo(def);
        } else {
            expandAffixAdjustWidth(null);
        }
    }

    /**
     * Creates a DecimalFormat from the given pattern and symbols. Use this constructor
     * when you need to completely customize the behavior of the format.
     *
     * <p>To obtain standard formats for a given locale, use the factory methods on
     * NumberFormat such as getInstance or getCurrencyInstance. If you need only minor
     * adjustments to a standard format, you can modify the format returned by a
     * NumberFormat factory method.
     *
     * @param pattern a non-localized pattern string
     * @param symbols the set of symbols to be used
     * @exception IllegalArgumentException if the given pattern is invalid
     * @see NumberFormat#getInstance
     * @see NumberFormat#getNumberInstance
     * @see NumberFormat#getCurrencyInstance
     * @see NumberFormat#getPercentInstance
     * @see DecimalFormatSymbols
     * @stable ICU 2.0
     */
    public DecimalFormat(String pattern, DecimalFormatSymbols symbols) {
        createFromPatternAndSymbols(pattern, symbols);
    }

    private void createFromPatternAndSymbols(String pattern, DecimalFormatSymbols inputSymbols) {
        // Always applyPattern after the symbols are set
        symbols = (DecimalFormatSymbols) inputSymbols.clone();
        setCurrencyForSymbols();
        applyPatternWithoutExpandAffix(pattern, false);
        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
            currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale());
        } else {
            expandAffixAdjustWidth(null);
        }
    }

    /**
     * Creates a DecimalFormat from the given pattern, symbols, information used for
     * currency plural format, and format style. Use this constructor when you need to
     * completely customize the behavior of the format.
     *
     * <p>To obtain standard formats for a given locale, use the factory methods on
     * NumberFormat such as getInstance or getCurrencyInstance.
     *
     * <p>If you need only minor adjustments to a standard format, you can modify the
     * format returned by a NumberFormat factory method using the setters.
     *
     * <p>If you want to completely customize a decimal format, using your own
     * DecimalFormatSymbols (such as group separators) and your own information for
     * currency plural formatting (such as plural rule and currency plural patterns), you
     * can use this constructor.
     *
     * @param pattern a non-localized pattern string
     * @param symbols the set of symbols to be used
     * @param infoInput the information used for currency plural format, including
     * currency plural patterns and plural rules.
     * @param style the decimal formatting style, it is one of the following values:
     * NumberFormat.NUMBERSTYLE; NumberFormat.CURRENCYSTYLE; NumberFormat.PERCENTSTYLE;
     * NumberFormat.SCIENTIFICSTYLE; NumberFormat.INTEGERSTYLE;
     * NumberFormat.ISOCURRENCYSTYLE; NumberFormat.PLURALCURRENCYSTYLE;
     * @stable ICU 4.2
     */
    public DecimalFormat(String pattern, DecimalFormatSymbols symbols, CurrencyPluralInfo infoInput,
                         int style) {
        CurrencyPluralInfo info = infoInput;
        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
            info = (CurrencyPluralInfo) infoInput.clone();
        }
        create(pattern, symbols, info, style);
    }

    private void create(String pattern, DecimalFormatSymbols inputSymbols, CurrencyPluralInfo info,
                        int inputStyle) {
        if (inputStyle != NumberFormat.PLURALCURRENCYSTYLE) {
            createFromPatternAndSymbols(pattern, inputSymbols);
        } else {
            // Always applyPattern after the symbols are set
            symbols = (DecimalFormatSymbols) inputSymbols.clone();
            currencyPluralInfo = info;
            // the pattern used in format is not fixed until formatting, in which, the
            // number is known and will be used to pick the right pattern based on plural
            // count.  Here, set the pattern as the pattern of plural count == "other".
            // For most locale, the patterns are probably the same for all plural
            // count. If not, the right pattern need to be re-applied during format.
            String currencyPluralPatternForOther =
                currencyPluralInfo.getCurrencyPluralPattern("other");
            applyPatternWithoutExpandAffix(currencyPluralPatternForOther, false);
            setCurrencyForSymbols();
        }
        style = inputStyle;
    }

    /**
     * Creates a DecimalFormat for currency plural format from the given pattern, symbols,
     * and style.
     */
    DecimalFormat(String pattern, DecimalFormatSymbols inputSymbols, int style) {
        CurrencyPluralInfo info = null;
        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
            info = new CurrencyPluralInfo(inputSymbols.getULocale());
        }
        create(pattern, inputSymbols, info, style);
    }

    /**
     * {@inheritDoc}
     * @stable ICU 2.0
     */
    @Override
    public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) {
        return format(number, result, fieldPosition, false);
    }

    // See if number is negative.
    // usage: isNegative(multiply(numberToBeFormatted));
    private boolean isNegative(double number) {
        // Detecting whether a double is negative is easy with the exception of the value
        // -0.0. This is a double which has a zero mantissa (and exponent), but a negative
        // sign bit. It is semantically distinct from a zero with a positive sign bit, and
        // this distinction is important to certain kinds of computations. However, it's a
        // little tricky to detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you
        // may ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==
        // -Infinity. Proper detection of -0.0 is needed to deal with the issues raised by
        // bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
        return (number < 0.0) || (number == 0.0 && 1 / number < 0.0);
    }

    // Rounds the number and strips of the negative sign.
    // usage: round(multiply(numberToBeFormatted))
    private double round(double number) {
        boolean isNegative = isNegative(number);
        if (isNegative)
            number = -number;

        // Apply rounding after multiplier
        if (roundingDouble > 0.0) {
            // number = roundingDouble
            //    * round(number / roundingDouble, roundingMode, isNegative);
            return round(
                number, roundingDouble, roundingDoubleReciprocal, roundingMode,
                isNegative);
        }
        return number;
    }

    // Multiplies given number by multipler (if there is one) returning the new
    // number. If there is no multiplier, returns the number passed in unchanged.
    private double multiply(double number) {
        if (multiplier != 1) {
            return number * multiplier;
        }
        return number;
    }

    // [Spark/CDL] The actual method to format number. If boolean value
    // parseAttr == true, then attribute information will be recorded.
    private StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition,
                                boolean parseAttr) {
        fieldPosition.setBeginIndex(0);
        fieldPosition.setEndIndex(0);

        if (Double.isNaN(number)) {
            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
                fieldPosition.setBeginIndex(result.length());
            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
                fieldPosition.setBeginIndex(result.length());
            }

            result.append(symbols.getNaN());
            // [Spark/CDL] Add attribute for NaN here.
            // result.append(symbols.getNaN());
            if (parseAttr) {
                addAttribute(Field.INTEGER, result.length() - symbols.getNaN().length(),
                             result.length());
            }
            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
                fieldPosition.setEndIndex(result.length());
            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
                fieldPosition.setEndIndex(result.length());
            }

            addPadding(result, fieldPosition, 0, 0);
            return result;
        }

        // Do this BEFORE checking to see if value is negative or infinite and
        // before rounding.
        number = multiply(number);
        boolean isNegative = isNegative(number);
        number = round(number);

        if (Double.isInfinite(number)) {
            int prefixLen = appendAffix(result, isNegative, true, parseAttr);

            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
                fieldPosition.setBeginIndex(result.length());
            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
                fieldPosition.setBeginIndex(result.length());
            }

            // [Spark/CDL] Add attribute for infinity here.
            result.append(symbols.getInfinity());
            if (parseAttr) {
                addAttribute(Field.INTEGER, result.length() - symbols.getInfinity().length(),
                             result.length());
            }
            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
                fieldPosition.setEndIndex(result.length());
            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
                fieldPosition.setEndIndex(result.length());
            }

            int suffixLen = appendAffix(result, isNegative, false, parseAttr);

            addPadding(result, fieldPosition, prefixLen, suffixLen);
            return result;
        }

        // At this point we are guaranteed a nonnegative finite
        // number.
        synchronized (digitList) {
            digitList.set(number, precision(false), !useExponentialNotation &&
                          !areSignificantDigitsUsed());
            return subformat(number, result, fieldPosition, isNegative, false, parseAttr);
        }
    }

    /**
     * This is a special function used by the CompactDecimalFormat subclass.
     * It completes only the rounding portion of the formatting and returns
     * the resulting double. CompactDecimalFormat uses the result to compute
     * the plural form to use.
     *
     * @param number The number to format.
     * @return The number rounded to the correct number of significant digits
     * with negative sign stripped off.
     * @internal
     * @deprecated
     */
    @Deprecated
    double adjustNumberAsInFormatting(double number) {
        if (Double.isNaN(number)) {
            return number;
        }
        number = round(multiply(number));
        if (Double.isInfinite(number)) {
            return number;
        }
        return toDigitList(number).getDouble();
    }
    
    @Deprecated
    DigitList toDigitList(double number) {
        DigitList result = new DigitList();
        result.set(number, precision(false), false);
        return result;
    }

    /**
      * This is a special function used by the CompactDecimalFormat subclass
      * to determine if the number to be formatted is negative.
      *
      * @param number The number to format.
      * @return True if number is negative.
      * @internal
      * @deprecated
      */
     @Deprecated
     boolean isNumberNegative(double number) {
         if (Double.isNaN(number)) {
             return false;
         }
         return isNegative(multiply(number));
     }

    /**
     * Round a double value to the nearest multiple of the given rounding increment,
     * according to the given mode. This is equivalent to rounding value/roundingInc to
     * the nearest integer, according to the given mode, and returning that integer *
     * roundingInc. Note this is changed from the version in 2.4, since division of
     * doubles have inaccuracies. jitterbug 1871.
     *
     * @param number
     *            the absolute value of the number to be rounded
     * @param roundingInc
     *            the rounding increment
     * @param roundingIncReciprocal
     *            if non-zero, is the
     * @param mode
     *            a BigDecimal rounding mode
     * @param isNegative
     *            true if the number to be rounded is negative
     * @return the absolute value of the rounded result
     */
    private static double round(double number, double roundingInc, double roundingIncReciprocal,
                                int mode, boolean isNegative) {

        double div = roundingIncReciprocal == 0.0 ? number / roundingInc : number *
            roundingIncReciprocal;

        // do the absolute cases first

        switch (mode) {
        case BigDecimal.ROUND_CEILING:
            div = (isNegative ? Math.floor(div + epsilon) : Math.ceil(div - epsilon));
            break;
        case BigDecimal.ROUND_FLOOR:
            div = (isNegative ? Math.ceil(div - epsilon) : Math.floor(div + epsilon));
            break;
        case BigDecimal.ROUND_DOWN:
            div = (Math.floor(div + epsilon));
            break;
        case BigDecimal.ROUND_UP:
            div = (Math.ceil(div - epsilon));
            break;
        case BigDecimal.ROUND_UNNECESSARY:
            if (div != Math.floor(div)) {
                throw new ArithmeticException("Rounding necessary");
            }
            return number;
        default:

            // Handle complex cases, where the choice depends on the closer value.

            // We figure out the distances to the two possible values, ceiling and floor.
            // We then go for the diff that is smaller.  Only if they are equal does the
            // mode matter.

            double ceil = Math.ceil(div);
            double ceildiff = ceil - div; // (ceil * roundingInc) - number;
            double floor = Math.floor(div);
            double floordiff = div - floor; // number - (floor * roundingInc);

            // Note that the diff values were those mapped back to the "normal" space by
            // using the roundingInc. I don't have access to the original author of the
            // code but suspect that that was to produce better result in edge cases
            // because of machine precision, rather than simply using the difference
            // between, say, ceil and div.  However, it didn't work in all cases. Am
            // trying instead using an epsilon value.

            switch (mode) {
            case BigDecimal.ROUND_HALF_EVEN:
                // We should be able to just return Math.rint(a), but this
                // doesn't work in some VMs.
                // if one is smaller than the other, take the corresponding side
                if (floordiff + epsilon < ceildiff) {
                    div = floor;
                } else if (ceildiff + epsilon < floordiff) {
                    div = ceil;
                } else { // they are equal, so we want to round to whichever is even
                    double testFloor = floor / 2;
                    div = (testFloor == Math.floor(testFloor)) ? floor : ceil;
                }
                break;
            case BigDecimal.ROUND_HALF_DOWN:
                div = ((floordiff <= ceildiff + epsilon) ? floor : ceil);
                break;
            case BigDecimal.ROUND_HALF_UP:
                div = ((ceildiff <= floordiff + epsilon) ? ceil : floor);
                break;
            default:
                throw new IllegalArgumentException("Invalid rounding mode: " + mode);
            }
        }
        number = roundingIncReciprocal == 0.0 ? div * roundingInc : div / roundingIncReciprocal;
        return number;
    }

    private static double epsilon = 0.00000000001;

    /**
     * @stable ICU 2.0
     */
    // [Spark/CDL] Delegate to format_long_StringBuffer_FieldPosition_boolean
    @Override
    public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) {
        return format(number, result, fieldPosition, false);
    }

    private StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition,
                                boolean parseAttr) {
        fieldPosition.setBeginIndex(0);
        fieldPosition.setEndIndex(0);

        // If we are to do rounding, we need to move into the BigDecimal
        // domain in order to do divide/multiply correctly.
        if (actualRoundingIncrementICU != null) {
            return format(BigDecimal.valueOf(number), result, fieldPosition);
        }

        boolean isNegative = (number < 0);
        if (isNegative)
            number = -number;

        // In general, long values always represent real finite numbers, so we don't have
        // to check for +/- Infinity or NaN. However, there is one case we have to be
        // careful of: The multiplier can push a number near MIN_VALUE or MAX_VALUE
        // outside the legal range. We check for this before multiplying, and if it
        // happens we use BigInteger instead.
        if (multiplier != 1) {
            boolean tooBig = false;
            if (number < 0) { // This can only happen if number == Long.MIN_VALUE
                long cutoff = Long.MIN_VALUE / multiplier;
                tooBig = (number <= cutoff); // number == cutoff can only happen if multiplier == -1
            } else {
                long cutoff = Long.MAX_VALUE / multiplier;
                tooBig = (number > cutoff);
            }
            if (tooBig) {
                // [Spark/CDL] Use
                // format_BigInteger_StringBuffer_FieldPosition_boolean instead
                // parseAttr is used to judge whether to synthesize attributes.
                return format(BigInteger.valueOf(isNegative ? -number : number), result,
                              fieldPosition, parseAttr);
            }
        }

        number *= multiplier;
        synchronized (digitList) {
            digitList.set(number, precision(true));
            return subformat(number, result, fieldPosition, isNegative, true, parseAttr);
        }
    }

    /**
     * Formats a BigInteger number.
     *
     * @stable ICU 2.0
     */
    @Override
    public StringBuffer format(BigInteger number, StringBuffer result,
                               FieldPosition fieldPosition) {
        return format(number, result, fieldPosition, false);
    }

    private StringBuffer format(BigInteger number, StringBuffer result, FieldPosition fieldPosition,
                                boolean parseAttr) {
        // If we are to do rounding, we need to move into the BigDecimal
        // domain in order to do divide/multiply correctly.
        if (actualRoundingIncrementICU != null) {
            return format(new BigDecimal(number), result, fieldPosition);
        }

        if (multiplier != 1) {
            number = number.multiply(BigInteger.valueOf(multiplier));
        }

        // At this point we are guaranteed a nonnegative finite
        // number.
        synchronized (digitList) {
            digitList.set(number, precision(true));
            return subformat(number.intValue(), result, fieldPosition, number.signum() < 0, true,
                             parseAttr);
        }
    }

    /**
     * Formats a BigDecimal number.
     *
     * @stable ICU 2.0
     */
    @Override
    public StringBuffer format(java.math.BigDecimal number, StringBuffer result,
                               FieldPosition fieldPosition) {
        return format(number, result, fieldPosition, false);
    }

    private StringBuffer format(java.math.BigDecimal number, StringBuffer result,
                                FieldPosition fieldPosition,
            boolean parseAttr) {
        if (multiplier != 1) {
            number = number.multiply(java.math.BigDecimal.valueOf(multiplier));
        }

        if (actualRoundingIncrement != null) {
            number = number.divide(actualRoundingIncrement, 0, roundingMode).multiply(actualRoundingIncrement);
        }

        synchronized (digitList) {
            digitList.set(number, precision(false), !useExponentialNotation &&
                          !areSignificantDigitsUsed());
            return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,
                             false, parseAttr);
        }
    }

    /**
     * Formats a BigDecimal number.
     *
     * @stable ICU 2.0
     */
    @Override
    public StringBuffer format(BigDecimal number, StringBuffer result,
                               FieldPosition fieldPosition) {
         // This method is just a copy of the corresponding java.math.BigDecimal method
         // for now. It isn't very efficient since it must create a conversion object to
         // do math on the rounding increment. In the future we may try to clean this up,
         // or even better, limit our support to just one flavor of BigDecimal.
        if (multiplier != 1) {
            number = number.multiply(BigDecimal.valueOf(multiplier), mathContext);
        }

        if (actualRoundingIncrementICU != null) {
            number = number.divide(actualRoundingIncrementICU, 0, roundingMode)
                .multiply(actualRoundingIncrementICU, mathContext);
        }

        synchronized (digitList) {
            digitList.set(number, precision(false), !useExponentialNotation &&
                          !areSignificantDigitsUsed());
            return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,
                             false, false);
        }
    }

    /**
     * Returns true if a grouping separator belongs at the given position, based on whether
     * grouping is in use and the values of the primary and secondary grouping interval.
     *
     * @param pos the number of integer digits to the right of the current position. Zero
     * indicates the position after the rightmost integer digit.
     * @return true if a grouping character belongs at the current position.
     */
    private boolean isGroupingPosition(int pos) {
        boolean result = false;
        if (isGroupingUsed() && (pos > 0) && (groupingSize > 0)) {
            if ((groupingSize2 > 0) && (pos > groupingSize)) {
                result = ((pos - groupingSize) % groupingSize2) == 0;
            } else {
                result = pos % groupingSize == 0;
            }
        }
        return result;
    }

    /**
     * Return the number of fraction digits to display, or the total
     * number of digits for significant digit formats and exponential
     * formats.
     */
    private int precision(boolean isIntegral) {
        if (areSignificantDigitsUsed()) {
            return getMaximumSignificantDigits();
        } else if (useExponentialNotation) {
            return getMinimumIntegerDigits() + getMaximumFractionDigits();
        } else {
            return isIntegral ? 0 : getMaximumFractionDigits();
        }
    }

    private StringBuffer subformat(int number, StringBuffer result, FieldPosition fieldPosition,
                                   boolean isNegative, boolean isInteger, boolean parseAttr) {
        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
            // compute the plural category from the digitList plus other settings
            return subformat(currencyPluralInfo.select(getFixedDecimal(number)),
                             result, fieldPosition, isNegative,
                             isInteger, parseAttr);
        } else {
            return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
        }
    }

    /**
     * This is ugly, but don't see a better way to do it without major restructuring of the code.
     */
    /*package*/ FixedDecimal getFixedDecimal(double number) {
        // get the visible fractions and the number of fraction digits.
       return getFixedDecimal(number, digitList);
    }
    
    FixedDecimal getFixedDecimal(double number, DigitList dl) {
        int fractionalDigitsInDigitList = dl.count - dl.decimalAt;
        int v;
        long f;
        int maxFractionalDigits;
        int minFractionalDigits;
        if (useSignificantDigits) {
            maxFractionalDigits = maxSignificantDigits - dl.decimalAt;
            minFractionalDigits = minSignificantDigits - dl.decimalAt;
            if (minFractionalDigits < 0) {
                minFractionalDigits = 0;
            }
            if (maxFractionalDigits < 0) {
                maxFractionalDigits = 0;
            }
        } else {
            maxFractionalDigits = getMaximumFractionDigits();
            minFractionalDigits = getMinimumFractionDigits();
        }
        v = fractionalDigitsInDigitList;
        if (v < minFractionalDigits) {
            v = minFractionalDigits;
        } else if (v > maxFractionalDigits) {
            v = maxFractionalDigits;
        }
        f = 0;
        if (v > 0) {
            for (int i = Math.max(0, dl.decimalAt); i < dl.count; ++i) {
                f *= 10;
                f += (dl.digits[i] - '0');
            }
            for (int i = v; i < fractionalDigitsInDigitList; ++i) {
                f *= 10;
            }
        }
        return new FixedDecimal(number, v, f);
    }

    private StringBuffer subformat(double number, StringBuffer result, FieldPosition fieldPosition,
                                   boolean isNegative,
            boolean isInteger, boolean parseAttr) {
        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
            // compute the plural category from the digitList plus other settings
            return subformat(currencyPluralInfo.select(getFixedDecimal(number)),
                             result, fieldPosition, isNegative,
                             isInteger, parseAttr);
        } else {
            return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
        }
    }

    private StringBuffer subformat(String pluralCount, StringBuffer result, FieldPosition fieldPosition,
            boolean isNegative, boolean isInteger, boolean parseAttr) {
        // There are 2 ways to activate currency plural format: by applying a pattern with
        // 3 currency sign directly, or by instantiate a decimal formatter using
        // PLURALCURRENCYSTYLE.  For both cases, the number of currency sign in the
        // pattern is 3.  Even if the number of currency sign in the pattern is 3, it does
        // not mean we need to reset the pattern.  For 1st case, we do not need to reset
        // pattern.  For 2nd case, we might need to reset pattern, if the default pattern
        // (corresponding to plural count 'other') we use is different from the pattern
        // based on 'pluralCount'.
        //
        // style is only valid when decimal formatter is constructed through
        // DecimalFormat(pattern, symbol, style)
        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
            // May need to reset pattern if the style is PLURALCURRENCYSTYLE.
            String currencyPluralPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount);
            if (formatPattern.equals(currencyPluralPattern) == false) {
                applyPatternWithoutExpandAffix(currencyPluralPattern, false);
            }
        }
        // Expand the affix to the right name according to the plural rule.  This is only
        // used for currency plural formatting.  Currency plural name is not a fixed
        // static one, it is a dynamic name based on the currency plural count.  So, the
        // affixes need to be expanded here.  For other cases, the affix is a static one
        // based on pattern alone, and it is already expanded during applying pattern, or
        // setDecimalFormatSymbols, or setCurrency.
        expandAffixAdjustWidth(pluralCount);
        return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
    }

    /**
     * Complete the formatting of a finite number. On entry, the
     * digitList must be filled in with the correct digits.
     */
    private StringBuffer subformat(StringBuffer result, FieldPosition fieldPosition,
                                   boolean isNegative, boolean isInteger, boolean parseAttr) {
        // NOTE: This isn't required anymore because DigitList takes care of this.
        //
        // // The negative of the exponent represents the number of leading // zeros
        // between the decimal and the first non-zero digit, for // a value < 0.1 (e.g.,
        // for 0.00123, -fExponent == 2). If this // is more than the maximum fraction
        // digits, then we have an underflow // for the printed representation. We
        // recognize this here and set // the DigitList representation to zero in this
        // situation.
        //
        // if (-digitList.decimalAt >= getMaximumFractionDigits())
        // {
        // digitList.count = 0;
        // }



        // Per bug 4147706, DecimalFormat must respect the sign of numbers which format as
        // zero. This allows sensible computations and preserves relations such as
        // signum(1/x) = signum(x), where x is +Infinity or -Infinity.  Prior to this fix,
        // we always formatted zero values as if they were positive. Liu 7/6/98.
        if (digitList.isZero()) {
            digitList.decimalAt = 0; // Normalize
        }

        int prefixLen = appendAffix(result, isNegative, true, parseAttr);

        if (useExponentialNotation) {
            subformatExponential(result, fieldPosition, parseAttr);
        } else {
            subformatFixed(result, fieldPosition, isInteger, parseAttr);
        }

        int suffixLen = appendAffix(result, isNegative, false, parseAttr);

        addPadding(result, fieldPosition, prefixLen, suffixLen);
        return result;
    }

    private void subformatFixed(StringBuffer result,
            FieldPosition fieldPosition,
            boolean isInteger,
            boolean parseAttr) {
        char [] digits = symbols.getDigitsLocal();

        char grouping = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ?
                symbols.getGroupingSeparator(): symbols.getMonetaryGroupingSeparator();
        char decimal = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ?
                symbols.getDecimalSeparator() : symbols.getMonetaryDecimalSeparator();
        boolean useSigDig = areSignificantDigitsUsed();
        int maxIntDig = getMaximumIntegerDigits();
        int minIntDig = getMinimumIntegerDigits();
        int i;
        // [Spark/CDL] Record the integer start index.
        int intBegin = result.length();
        // Record field information for caller.
        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
            fieldPosition.setBeginIndex(result.length());
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
            fieldPosition.setBeginIndex(result.length());
        }
        long fractionalDigits = 0;
        int fractionalDigitsCount = 0;
        boolean recordFractionDigits = false;

        int sigCount = 0;
        int minSigDig = getMinimumSignificantDigits();
        int maxSigDig = getMaximumSignificantDigits();
        if (!useSigDig) {
            minSigDig = 0;
            maxSigDig = Integer.MAX_VALUE;
        }

        // Output the integer portion. Here 'count' is the total number of integer
        // digits we will display, including both leading zeros required to satisfy
        // getMinimumIntegerDigits, and actual digits present in the number.
        int count = useSigDig ? Math.max(1, digitList.decimalAt) : minIntDig;
        if (digitList.decimalAt > 0 && count < digitList.decimalAt) {
            count = digitList.decimalAt;
        }

        // Handle the case where getMaximumIntegerDigits() is smaller than the real
        // number of integer digits. If this is so, we output the least significant
        // max integer digits. For example, the value 1997 printed with 2 max integer
        // digits is just "97".

        int digitIndex = 0; // Index into digitList.fDigits[]
        if (count > maxIntDig && maxIntDig >= 0) {
            count = maxIntDig;
            digitIndex = digitList.decimalAt - count;
        }

        int sizeBeforeIntegerPart = result.length();
        for (i = count - 1; i >= 0; --i) {
            if (i < digitList.decimalAt && digitIndex < digitList.count
                && sigCount < maxSigDig) {
                // Output a real digit
                result.append(digits[digitList.getDigitValue(digitIndex++)]);
                ++sigCount;
            } else {
                // Output a zero (leading or trailing)
                result.append(digits[0]);
                if (sigCount > 0) {
                    ++sigCount;
                }
            }

            // Output grouping separator if necessary.
            if (isGroupingPosition(i)) {
                result.append(grouping);
                // [Spark/CDL] Add grouping separator attribute here.
                if (parseAttr) {
                    // Length of grouping separator is 1.
                    addAttribute(Field.GROUPING_SEPARATOR, result.length() - 1, result.length());
                }
            }
        }

        // Record field information for caller.
        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
            fieldPosition.setEndIndex(result.length());
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
            fieldPosition.setEndIndex(result.length());
        }
        
        // This handles the special case of formatting 0. For zero only, we count the
        // zero to the left of the decimal point as one signficant digit. Ordinarily we
        // do not count any leading 0's as significant. If the number we are formatting
        // is not zero, then either sigCount or digits.getCount() will be non-zero.
        if (sigCount == 0 && digitList.count == 0) {
          sigCount = 1;
        }      

        // Determine whether or not there are any printable fractional digits. If
        // we've used up the digits we know there aren't.
        boolean fractionPresent = (!isInteger && digitIndex < digitList.count)
                || (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0));

        // If there is no fraction present, and we haven't printed any integer digits,
        // then print a zero. Otherwise we won't print _any_ digits, and we won't be
        // able to parse this string.
        if (!fractionPresent && result.length() == sizeBeforeIntegerPart)
            result.append(digits[0]);
        // [Spark/CDL] Add attribute for integer part.
        if (parseAttr) {
            addAttribute(Field.INTEGER, intBegin, result.length());
        }
        // Output the decimal separator if we always do so.
        if (decimalSeparatorAlwaysShown || fractionPresent) {
            if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
                fieldPosition.setBeginIndex(result.length());
            }
            result.append(decimal);
            if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
                fieldPosition.setEndIndex(result.length());
            }
            // [Spark/CDL] Add attribute for decimal separator
            if (parseAttr) {
                addAttribute(Field.DECIMAL_SEPARATOR, result.length() - 1, result.length());
            }
        }

        // Record field information for caller.
        if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
            fieldPosition.setBeginIndex(result.length());
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
            fieldPosition.setBeginIndex(result.length());
        }

        // [Spark/CDL] Record the begin index of fraction part.
        int fracBegin = result.length();
        recordFractionDigits = fieldPosition instanceof UFieldPosition;

        count = useSigDig ? Integer.MAX_VALUE : getMaximumFractionDigits();
        if (useSigDig && (sigCount == maxSigDig ||
                          (sigCount >= minSigDig && digitIndex == digitList.count))) {
            count = 0;
        }
        for (i = 0; i < count; ++i) {
            // Here is where we escape from the loop. We escape if we've output the
            // maximum fraction digits (specified in the for expression above). We
            // also stop when we've output the minimum digits and either: we have an
            // integer, so there is no fractional stuff to display, or we're out of
            // significant digits.
            if (!useSigDig && i >= getMinimumFractionDigits() &&
                (isInteger || digitIndex >= digitList.count)) {
                break;
            }

            // Output leading fractional zeros. These are zeros that come after the
            // decimal but before any significant digits. These are only output if
            // abs(number being formatted) < 1.0.
            if (-1 - i > (digitList.decimalAt - 1)) {
                result.append(digits[0]);
                if (recordFractionDigits) {
                    ++fractionalDigitsCount;
                    fractionalDigits *= 10;
                }
                continue;
            }

            // Output a digit, if we have any precision left, or a zero if we
            // don't. We don't want to output noise digits.
            if (!isInteger && digitIndex < digitList.count) {
                byte digit = digitList.getDigitValue(digitIndex++);
                result.append(digits[digit]);
                if (recordFractionDigits) {
                    ++fractionalDigitsCount;
                    fractionalDigits *= 10;
                    fractionalDigits += digit;
                }
            } else {
                result.append(digits[0]);
                if (recordFractionDigits) {
                    ++fractionalDigitsCount;
                    fractionalDigits *= 10;
                }
            }

            // If we reach the maximum number of significant digits, or if we output
            // all the real digits and reach the minimum, then we are done.
            ++sigCount;
            if (useSigDig && (sigCount == maxSigDig ||
                              (digitIndex == digitList.count && sigCount >= minSigDig))) {
                break;
            }
        }

        // Record field information for caller.
        if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
            fieldPosition.setEndIndex(result.length());
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
            fieldPosition.setEndIndex(result.length());
        }
        if (recordFractionDigits) {
            ((UFieldPosition) fieldPosition).setFractionDigits(fractionalDigitsCount, fractionalDigits);
        }

        // [Spark/CDL] Add attribute information if necessary.
        if (parseAttr && (decimalSeparatorAlwaysShown || fractionPresent)) {
            addAttribute(Field.FRACTION, fracBegin, result.length());
        }
    }

    private void subformatExponential(StringBuffer result,
            FieldPosition fieldPosition,
            boolean parseAttr) {
        char [] digits = symbols.getDigitsLocal();
        char decimal = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ?
                symbols.getDecimalSeparator() : symbols.getMonetaryDecimalSeparator();
        boolean useSigDig = areSignificantDigitsUsed();
        int maxIntDig = getMaximumIntegerDigits();
        int minIntDig = getMinimumIntegerDigits();
        int i;
        // Record field information for caller.
        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
            fieldPosition.setBeginIndex(result.length());
            fieldPosition.setEndIndex(-1);
        } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
            fieldPosition.setBeginIndex(-1);
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
            fieldPosition.setBeginIndex(result.length());
            fieldPosition.setEndIndex(-1);
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
            fieldPosition.setBeginIndex(-1);
        }


        // [Spark/CDL]
        // the begin index of integer part
        // the end index of integer part
        // the begin index of fractional part
        int intBegin = result.length();
        int intEnd = -1;
        int fracBegin = -1;
        int minFracDig = 0;
        if (useSigDig) {
            maxIntDig = minIntDig = 1;
            minFracDig = getMinimumSignificantDigits() - 1;
        } else {
            minFracDig = getMinimumFractionDigits();
            if (maxIntDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
                maxIntDig = 1;
                if (maxIntDig < minIntDig) {
                    maxIntDig = minIntDig;
                }
            }
            if (maxIntDig > minIntDig) {
                minIntDig = 1;
            }
        }
        long fractionalDigits = 0;
        int fractionalDigitsCount = 0;
        boolean recordFractionDigits = false;

        // Minimum integer digits are handled in exponential format by adjusting the
        // exponent. For example, 0.01234 with 3 minimum integer digits is "123.4E-4".

        // Maximum integer digits are interpreted as indicating the repeating
        // range. This is useful for engineering notation, in which the exponent is
        // restricted to a multiple of 3. For example, 0.01234 with 3 maximum integer
        // digits is "12.34e-3".  If maximum integer digits are defined and are larger
        // than minimum integer digits, then minimum integer digits are ignored.

        int exponent = digitList.decimalAt;
        if (maxIntDig > 1 && maxIntDig != minIntDig) {
            // A exponent increment is defined; adjust to it.
            exponent = (exponent > 0) ? (exponent - 1) / maxIntDig : (exponent / maxIntDig) - 1;
            exponent *= maxIntDig;
        } else {
            // No exponent increment is defined; use minimum integer digits.
            // If none is specified, as in "#E0", generate 1 integer digit.
            exponent -= (minIntDig > 0 || minFracDig > 0) ? minIntDig : 1;
        }

        // We now output a minimum number of digits, and more if there are more
        // digits, up to the maximum number of digits. We place the decimal point
        // after the "integer" digits, which are the first (decimalAt - exponent)
        // digits.
        int minimumDigits = minIntDig + minFracDig;
        // The number of integer digits is handled specially if the number
        // is zero, since then there may be no digits.
        int integerDigits = digitList.isZero() ? minIntDig : digitList.decimalAt - exponent;
        int totalDigits = digitList.count;
        if (minimumDigits > totalDigits)
            totalDigits = minimumDigits;
        if (integerDigits > totalDigits)
            totalDigits = integerDigits;

        for (i = 0; i < totalDigits; ++i) {
            if (i == integerDigits) {
                // Record field information for caller.
                if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
                    fieldPosition.setEndIndex(result.length());
                } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
                    fieldPosition.setEndIndex(result.length());
                }

                // [Spark/CDL] Add attribute for integer part
                if (parseAttr) {
                    intEnd = result.length();
                    addAttribute(Field.INTEGER, intBegin, result.length());
                }
                result.append(decimal);
                // [Spark/CDL] Add attribute for decimal separator
                if (parseAttr) {
                    // Length of decimal separator is 1.
                    int decimalSeparatorBegin = result.length() - 1;
                    addAttribute(Field.DECIMAL_SEPARATOR, decimalSeparatorBegin,
                                 result.length());
                    fracBegin = result.length();
                }
                // Record field information for caller.
                if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
                    fieldPosition.setBeginIndex(result.length());
                } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
                    fieldPosition.setBeginIndex(result.length());
                }
                recordFractionDigits = fieldPosition instanceof UFieldPosition;

            }
            byte digit = (i < digitList.count) ? digitList.getDigitValue(i) : (byte)0;
            result.append(digits[digit]);
            if (recordFractionDigits) {
                ++fractionalDigitsCount;
                fractionalDigits *= 10;
                fractionalDigits += digit;
            }
        }

        // For ICU compatibility and format 0 to 0E0 with pattern "#E0" [Richard/GCL]
        if (digitList.isZero() && (totalDigits == 0)) {
            result.append(digits[0]);
        }

        // Record field information
        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
            if (fieldPosition.getEndIndex() < 0) {
                fieldPosition.setEndIndex(result.length());
            }
        } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
            if (fieldPosition.getBeginIndex() < 0) {
                fieldPosition.setBeginIndex(result.length());
            }
            fieldPosition.setEndIndex(result.length());
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
            if (fieldPosition.getEndIndex() < 0) {
                fieldPosition.setEndIndex(result.length());
            }
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
            if (fieldPosition.getBeginIndex() < 0) {
                fieldPosition.setBeginIndex(result.length());
            }
            fieldPosition.setEndIndex(result.length());
        }
        if (recordFractionDigits) {
            ((UFieldPosition) fieldPosition).setFractionDigits(fractionalDigitsCount, fractionalDigits);
        }

        // [Spark/CDL] Calcuate the end index of integer part and fractional
        // part if they are not properly processed yet.
        if (parseAttr) {
            if (intEnd < 0) {
                addAttribute(Field.INTEGER, intBegin, result.length());
            }
            if (fracBegin > 0) {
                addAttribute(Field.FRACTION, fracBegin, result.length());
            }
        }

        // The exponent is output using the pattern-specified minimum exponent
        // digits. There is no maximum limit to the exponent digits, since truncating
        // the exponent would result in an unacceptable inaccuracy.
        result.append(symbols.getExponentSeparator());
        // [Spark/CDL] For exponent symbol, add an attribute.
        if (parseAttr) {
            addAttribute(Field.EXPONENT_SYMBOL, result.length() -
                         symbols.getExponentSeparator().length(), result.length());
        }
        // For zero values, we force the exponent to zero. We must do this here, and
        // not earlier, because the value is used to determine integer digit count
        // above.
        if (digitList.isZero())
            exponent = 0;

        boolean negativeExponent = exponent < 0;
        if (negativeExponent) {
            exponent = -exponent;
            result.append(symbols.getMinusSign());
            // [Spark/CDL] If exponent has sign, then add an exponent sign
            // attribute.
            if (parseAttr) {
                // Length of exponent sign is 1.
                addAttribute(Field.EXPONENT_SIGN, result.length() - 1, result.length());
            }
        } else if (exponentSignAlwaysShown) {
            result.append(symbols.getPlusSign());
            // [Spark/CDL] Add an plus sign attribute.
            if (parseAttr) {
                // Length of exponent sign is 1.
                int expSignBegin = result.length() - 1;
                addAttribute(Field.EXPONENT_SIGN, expSignBegin, result.length());
            }
        }
        int expBegin = result.length();
        digitList.set(exponent);
        {
            int expDig = minExponentDigits;
            if (useExponentialNotation && expDig < 1) {
                expDig = 1;
            }
            for (i = digitList.decimalAt; i < expDig; ++i)
                result.append(digits[0]);
        }
        for (i = 0; i < digitList.decimalAt; ++i) {
            result.append((i < digitList.count) ? digits[digitList.getDigitValue(i)]
                          : digits[0]);
        }
        // [Spark/CDL] Add attribute for exponent part.
        if (parseAttr) {
            addAttribute(Field.EXPONENT, expBegin, result.length());
        }
    }

    private final void addPadding(StringBuffer result, FieldPosition fieldPosition, int prefixLen,
                                  int suffixLen) {
        if (formatWidth > 0) {
            int len = formatWidth - result.length();
            if (len > 0) {
                char[] padding = new char[len];
                for (int i = 0; i < len; ++i) {
                    padding[i] = pad;
                }
                switch (padPosition) {
                case PAD_AFTER_PREFIX:
                    result.insert(prefixLen, padding);
                    break;
                case PAD_BEFORE_PREFIX:
                    result.insert(0, padding);
                    break;
                case PAD_BEFORE_SUFFIX:
                    result.insert(result.length() - suffixLen, padding);
                    break;
                case PAD_AFTER_SUFFIX:
                    result.append(padding);
                    break;
                }
                if (padPosition == PAD_BEFORE_PREFIX || padPosition == PAD_AFTER_PREFIX) {
                    fieldPosition.setBeginIndex(fieldPosition.getBeginIndex() + len);
                    fieldPosition.setEndIndex(fieldPosition.getEndIndex() + len);
                }
            }
        }
    }

    /**
     * Parses the given string, returning a <code>Number</code> object to represent the
     * parsed value. <code>Double</code> objects are returned to represent non-integral
     * values which cannot be stored in a <code>BigDecimal</code>. These are
     * <code>NaN</code>, infinity, -infinity, and -0.0. If {@link #isParseBigDecimal()} is
     * false (the default), all other values are returned as <code>Long</code>,
     * <code>BigInteger</code>, or <code>BigDecimal</code> values, in that order of
     * preference. If {@link #isParseBigDecimal()} is true, all other values are returned
     * as <code>BigDecimal</code> valuse. If the parse fails, null is returned.
     *
     * @param text the string to be parsed
     * @param parsePosition defines the position where parsing is to begin, and upon
     * return, the position where parsing left off. If the position has not changed upon
     * return, then parsing failed.
     * @return a <code>Number</code> object with the parsed value or
     * <code>null</code> if the parse failed
     * @stable ICU 2.0
     */
    @Override
    public Number parse(String text, ParsePosition parsePosition) {
        return (Number) parse(text, parsePosition, null);
    }

    /**
     * Parses text from the given string as a CurrencyAmount. Unlike the parse() method,
     * this method will attempt to parse a generic currency name, searching for a match of
     * this object's locale's currency display names, or for a 3-letter ISO currency
     * code. This method will fail if this format is not a currency format, that is, if it
     * does not contain the currency pattern symbol (U+00A4) in its prefix or suffix.
     *
     * @param text the text to parse
     * @param pos input-output position; on input, the position within text to match; must
     *  have 0 <= pos.getIndex() < text.length(); on output, the position after the last
     *  matched character. If the parse fails, the position in unchanged upon output.
     * @return a CurrencyAmount, or null upon failure
     * @stable ICU 49
     */
    @Override
    public CurrencyAmount parseCurrency(CharSequence text, ParsePosition pos) {
        Currency[] currency = new Currency[1];
        return (CurrencyAmount) parse(text.toString(), pos, currency);
    }

    /**
     * Parses the given text as either a Number or a CurrencyAmount.
     *
     * @param text the string to parse
     * @param parsePosition input-output position; on input, the position within text to
     * match; must have 0 <= pos.getIndex() < text.length(); on output, the position after
     * the last matched character. If the parse fails, the position in unchanged upon
     * output.
     * @param currency if non-null, a CurrencyAmount is parsed and returned; otherwise a
     * Number is parsed and returned
     * @return a Number or CurrencyAmount or null
     */
    private Object parse(String text, ParsePosition parsePosition, Currency[] currency) {
        int backup;
        int i = backup = parsePosition.getIndex();

        // Handle NaN as a special case:

        // Skip padding characters, if around prefix
        if (formatWidth > 0 &&
            (padPosition == PAD_BEFORE_PREFIX || padPosition == PAD_AFTER_PREFIX)) {
            i = skipPadding(text, i);
        }
        if (text.regionMatches(i, symbols.getNaN(), 0, symbols.getNaN().length())) {
            i += symbols.getNaN().length();
            // Skip padding characters, if around suffix
            if (formatWidth > 0 && (padPosition == PAD_BEFORE_SUFFIX ||
                                    padPosition == PAD_AFTER_SUFFIX)) {
                i = skipPadding(text, i);
            }
            parsePosition.setIndex(i);
            return new Double(Double.NaN);
        }

        // NaN parse failed; start over
        i = backup;

        boolean[] status = new boolean[STATUS_LENGTH];
        if (currencySignCount != CURRENCY_SIGN_COUNT_ZERO) {
            if (!parseForCurrency(text, parsePosition, currency, status)) {
                return null;
            }
        } else {
            if (!subparse(text, parsePosition, digitList, status, currency, negPrefixPattern,
                          negSuffixPattern, posPrefixPattern, posSuffixPattern,
                          false, Currency.SYMBOL_NAME)) {
                parsePosition.setIndex(backup);
                return null;
            }
        }

        Number n = null;

        // Handle infinity
        if (status[STATUS_INFINITE]) {
            n = new Double(status[STATUS_POSITIVE] ? Double.POSITIVE_INFINITY :
                           Double.NEGATIVE_INFINITY);
        }

        // Handle underflow
        else if (status[STATUS_UNDERFLOW]) {
            n = status[STATUS_POSITIVE] ? new Double("0.0") : new Double("-0.0");
        }

        // Handle -0.0
        else if (!status[STATUS_POSITIVE] && digitList.isZero()) {
            n = new Double("-0.0");
        }

        else {
            // Do as much of the multiplier conversion as possible without
            // losing accuracy.
            int mult = multiplier; // Don't modify this.multiplier
            while (mult % 10 == 0) {
                --digitList.decimalAt;
                mult /= 10;
            }

            // Handle integral values
            if (!parseBigDecimal && mult == 1 && digitList.isIntegral()) {
                // hack quick long
                if (digitList.decimalAt < 12) { // quick check for long
                    long l = 0;
                    if (digitList.count > 0) {
                        int nx = 0;
                        while (nx < digitList.count) {
                            l = l * 10 + (char) digitList.digits[nx++] - '0';
                        }
                        while (nx++ < digitList.decimalAt) {
                            l *= 10;
                        }
                        if (!status[STATUS_POSITIVE]) {
                            l = -l;
                        }
                    }
                    n = Long.valueOf(l);
                } else {
                    BigInteger big = digitList.getBigInteger(status[STATUS_POSITIVE]);
                    n = (big.bitLength() < 64) ? (Number) Long.valueOf(big.longValue()) : (Number) big;
                }
            }
            // Handle non-integral values or the case where parseBigDecimal is set
            else {
                BigDecimal big = digitList.getBigDecimalICU(status[STATUS_POSITIVE]);
                n = big;
                if (mult != 1) {
                    n = big.divide(BigDecimal.valueOf(mult), mathContext);
                }
            }
        }

        // Assemble into CurrencyAmount if necessary
        return (currency != null) ? (Object) new CurrencyAmount(n, currency[0]) : (Object) n;
    }

    private boolean parseForCurrency(String text, ParsePosition parsePosition,
            Currency[] currency, boolean[] status) {
        int origPos = parsePosition.getIndex();
        if (!isReadyForParsing) {
            int savedCurrencySignCount = currencySignCount;
            setupCurrencyAffixForAllPatterns();
            // reset pattern back
            if (savedCurrencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
                applyPatternWithoutExpandAffix(formatPattern, false);
            } else {
                applyPattern(formatPattern, false);
            }
            isReadyForParsing = true;
        }
        int maxPosIndex = origPos;
        int maxErrorPos = -1;
        boolean[] savedStatus = null;
        // First, parse against current pattern.
        // Since current pattern could be set by applyPattern(),
        // it could be an arbitrary pattern, and it may not be the one
        // defined in current locale.
        boolean[] tmpStatus = new boolean[STATUS_LENGTH];
        ParsePosition tmpPos = new ParsePosition(origPos);
        DigitList tmpDigitList = new DigitList();
        boolean found;
        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
            found = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
                             negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,
                             true, Currency.LONG_NAME);
        } else {
            found = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
                             negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,
                             true, Currency.SYMBOL_NAME);
        }
        if (found) {
            if (tmpPos.getIndex() > maxPosIndex) {
                maxPosIndex = tmpPos.getIndex();
                savedStatus = tmpStatus;
                digitList = tmpDigitList;
            }
        } else {
            maxErrorPos = tmpPos.getErrorIndex();
        }
        // Then, parse against affix patterns.  Those are currency patterns and currency
        // plural patterns defined in the locale.
        for (AffixForCurrency affix : affixPatternsForCurrency) {
            tmpStatus = new boolean[STATUS_LENGTH];
            tmpPos = new ParsePosition(origPos);
            tmpDigitList = new DigitList();
            boolean result = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
                                      affix.getNegPrefix(), affix.getNegSuffix(),
                                      affix.getPosPrefix(), affix.getPosSuffix(),
                                      true, affix.getPatternType());
            if (result) {
                found = true;
                if (tmpPos.getIndex() > maxPosIndex) {
                    maxPosIndex = tmpPos.getIndex();
                    savedStatus = tmpStatus;
                    digitList = tmpDigitList;
                }
            } else {
                maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? tmpPos.getErrorIndex()
                    : maxErrorPos;
            }
        }
        // Finally, parse against simple affix to find the match.  For example, in
        // TestMonster suite, if the to-be-parsed text is "-\u00A40,00".
        // complexAffixCompare will not find match, since there is no ISO code matches
        // "\u00A4", and the parse stops at "\u00A4".  We will just use simple affix
        // comparison (look for exact match) to pass it.
        //
        // TODO: We should parse against simple affix first when
        // output currency is not requested. After the complex currency
        // parsing implementation was introduced, the default currency
        // instance parsing slowed down because of the new code flow.
        // I filed #10312 - Yoshito
        tmpStatus = new boolean[STATUS_LENGTH];
        tmpPos = new ParsePosition(origPos);
        tmpDigitList = new DigitList();

        // Disable complex currency parsing and try it again.
        boolean result = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
                                  negativePrefix, negativeSuffix, positivePrefix, positiveSuffix,
                                  false /* disable complex currency parsing */, Currency.SYMBOL_NAME);
        if (result) {
            if (tmpPos.getIndex() > maxPosIndex) {
                maxPosIndex = tmpPos.getIndex();
                savedStatus = tmpStatus;
                digitList = tmpDigitList;
            }
            found = true;
        } else {
            maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? tmpPos.getErrorIndex() :
                maxErrorPos;
        }

        if (!found) {
            // parsePosition.setIndex(origPos);
            parsePosition.setErrorIndex(maxErrorPos);
        } else {
            parsePosition.setIndex(maxPosIndex);
            parsePosition.setErrorIndex(-1);
            for (int index = 0; index < STATUS_LENGTH; ++index) {
                status[index] = savedStatus[index];
            }
        }
        return found;
    }

    // Get affix patterns used in locale's currency pattern (NumberPatterns[1]) and
    // currency plural pattern (CurrencyUnitPatterns).
    private void setupCurrencyAffixForAllPatterns() {
        if (currencyPluralInfo == null) {
            currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale());
        }
        affixPatternsForCurrency = new HashSet<AffixForCurrency>();

        // save the current pattern, since it will be changed by
        // applyPatternWithoutExpandAffix
        String savedFormatPattern = formatPattern;

        // CURRENCYSTYLE and ISOCURRENCYSTYLE should have the same prefix and suffix, so,
        // only need to save one of them.  Here, chose onlyApplyPatternWithoutExpandAffix
        // without saving the actualy pattern in 'pattern' data member.  TODO: is it uloc?
        applyPatternWithoutExpandAffix(getPattern(symbols.getULocale(), NumberFormat.CURRENCYSTYLE),
                                       false);
        AffixForCurrency affixes = new AffixForCurrency(
            negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,
            Currency.SYMBOL_NAME);
        affixPatternsForCurrency.add(affixes);

        // add plural pattern
        Iterator<String> iter = currencyPluralInfo.pluralPatternIterator();
        Set<String> currencyUnitPatternSet = new HashSet<String>();
        while (iter.hasNext()) {
            String pluralCount = iter.next();
            String currencyPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount);
            if (currencyPattern != null &&
                currencyUnitPatternSet.contains(currencyPattern) == false) {
                currencyUnitPatternSet.add(currencyPattern);
                applyPatternWithoutExpandAffix(currencyPattern, false);
                affixes = new AffixForCurrency(negPrefixPattern, negSuffixPattern, posPrefixPattern,
                                               posSuffixPattern, Currency.LONG_NAME);
                affixPatternsForCurrency.add(affixes);
            }
        }
        // reset pattern back
        formatPattern = savedFormatPattern;
    }

    // currency formatting style options
    private static final int CURRENCY_SIGN_COUNT_ZERO = 0;
    private static final int CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT = 1;
    private static final int CURRENCY_SIGN_COUNT_IN_ISO_FORMAT = 2;
    private static final int CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT = 3;

    private static final int STATUS_INFINITE = 0;
    private static final int STATUS_POSITIVE = 1;
    private static final int STATUS_UNDERFLOW = 2;
    private static final int STATUS_LENGTH = 3;

    private static final UnicodeSet dotEquivalents = new UnicodeSet(
            //"[.\u2024\u3002\uFE12\uFE52\uFF0E\uFF61]"
            0x002E, 0x002E,
            0x2024, 0x2024,
            0x3002, 0x3002,
            0xFE12, 0xFE12,
            0xFE52, 0xFE52,
            0xFF0E, 0xFF0E,
            0xFF61, 0xFF61).freeze();

    private static final UnicodeSet commaEquivalents = new UnicodeSet(
            //"[,\u060C\u066B\u3001\uFE10\uFE11\uFE50\uFE51\uFF0C\uFF64]"
            0x002C, 0x002C,
            0x060C, 0x060C,
            0x066B, 0x066B,
            0x3001, 0x3001,
            0xFE10, 0xFE11,
            0xFE50, 0xFE51,
            0xFF0C, 0xFF0C,
            0xFF64, 0xFF64).freeze();

//    private static final UnicodeSet otherGroupingSeparators = new UnicodeSet(
//            //"[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]"
//            0x0020, 0x0020,
//            0x0027, 0x0027,
//            0x00A0, 0x00A0,
//            0x066C, 0x066C,
//            0x2000, 0x200A,
//            0x2018, 0x2019,
//            0x202F, 0x202F,
//            0x205F, 0x205F,
//            0x3000, 0x3000,
//            0xFF07, 0xFF07).freeze();

    private static final UnicodeSet strictDotEquivalents = new UnicodeSet(
            //"[.\u2024\uFE52\uFF0E\uFF61]"
            0x002E, 0x002E,
            0x2024, 0x2024,
            0xFE52, 0xFE52,
            0xFF0E, 0xFF0E,
            0xFF61, 0xFF61).freeze();

    private static final UnicodeSet strictCommaEquivalents = new UnicodeSet(
            //"[,\u066B\uFE10\uFE50\uFF0C]"
            0x002C, 0x002C,
            0x066B, 0x066B,
            0xFE10, 0xFE10,
            0xFE50, 0xFE50,
            0xFF0C, 0xFF0C).freeze();

//    private static final UnicodeSet strictOtherGroupingSeparators = new UnicodeSet(
//            //"[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]"
//            0x0020, 0x0020,
//            0x0027, 0x0027,
//            0x00A0, 0x00A0,
//            0x066C, 0x066C,
//            0x2000, 0x200A,
//            0x2018, 0x2019,
//            0x202F, 0x202F,
//            0x205F, 0x205F,
//            0x3000, 0x3000,
//            0xFF07, 0xFF07).freeze();

    private static final UnicodeSet defaultGroupingSeparators =
        // new UnicodeSet(dotEquivalents).addAll(commaEquivalents)
        //     .addAll(otherGroupingSeparators).freeze();
        new UnicodeSet(
                0x0020, 0x0020,
                0x0027, 0x0027,
                0x002C, 0x002C,
                0x002E, 0x002E,
                0x00A0, 0x00A0,
                0x060C, 0x060C,
                0x066B, 0x066C,
                0x2000, 0x200A,
                0x2018, 0x2019,
                0x2024, 0x2024,
                0x202F, 0x202F,
                0x205F, 0x205F,
                0x3000, 0x3002,
                0xFE10, 0xFE12,
                0xFE50, 0xFE52,
                0xFF07, 0xFF07,
                0xFF0C, 0xFF0C,
                0xFF0E, 0xFF0E,
                0xFF61, 0xFF61,
                0xFF64, 0xFF64).freeze();

    private static final UnicodeSet strictDefaultGroupingSeparators =
        // new UnicodeSet(strictDotEquivalents).addAll(strictCommaEquivalents)
        //     .addAll(strictOtherGroupingSeparators).freeze();
        new UnicodeSet(
                0x0020, 0x0020,
                0x0027, 0x0027,
                0x002C, 0x002C,
                0x002E, 0x002E,
                0x00A0, 0x00A0,
                0x066B, 0x066C,
                0x2000, 0x200A,
                0x2018, 0x2019,
                0x2024, 0x2024,
                0x202F, 0x202F,
                0x205F, 0x205F,
                0x3000, 0x3000,
                0xFE10, 0xFE10,
                0xFE50, 0xFE50,
                0xFE52, 0xFE52,
                0xFF07, 0xFF07,
                0xFF0C, 0xFF0C,
                0xFF0E, 0xFF0E,
                0xFF61, 0xFF61).freeze();
    
    private static final UnicodeSet minusSigns =
        new UnicodeSet(
                0x002D, 0x002D,
                0x207B, 0x207B,
                0x208B, 0x208B,
                0x2212, 0x2212,
                0x2796, 0x2796,
                0xFE63, 0xFE63,
                0xFF0D, 0xFF0D).freeze();
    
    private static final UnicodeSet plusSigns =
            new UnicodeSet(
                0x002B, 0x002B,
                0x207A, 0x207A,
                0x208A, 0x208A,
                0x2795, 0x2795,
                0xFB29, 0xFB29,
                0xFE62, 0xFE62,
                0xFF0B, 0xFF0B).freeze();
    

    // When parsing a number with big exponential value, it requires to transform the
    // value into a string representation to construct BigInteger instance.  We want to
    // set the maximum size because it can easily trigger OutOfMemoryException.
    // PARSE_MAX_EXPONENT is currently set to 1000 (See getParseMaxDigits()),
    // which is much bigger than MAX_VALUE of Double ( See the problem reported by ticket#5698
    private int PARSE_MAX_EXPONENT = 1000;

    /**
     * Parses the given text into a number. The text is parsed beginning at parsePosition,
     * until an unparseable character is seen.
     *
     * @param text the string to parse.
     * @param parsePosition the position at which to being parsing. Upon return, the first
     * unparseable character.
     * @param digits the DigitList to set to the parsed value.
     * @param status Upon return contains boolean status flags indicating whether the
     * value was infinite and whether it was positive.
     * @param currency return value for parsed currency, for generic currency parsing
     * mode, or null for normal parsing. In generic currency parsing mode, any currency is
     * parsed, not just the currency that this formatter is set to.
     * @param negPrefix negative prefix pattern
     * @param negSuffix negative suffix pattern
     * @param posPrefix positive prefix pattern
     * @param negSuffix negative suffix pattern
     * @param complexCurrencyParsing whether it is complex currency parsing or not.
     * @param type type of currency to parse against, LONG_NAME only or not.
     */
    private final boolean subparse(
        String text, ParsePosition parsePosition, DigitList digits,
        boolean status[], Currency currency[], String negPrefix, String negSuffix, String posPrefix,
        String posSuffix, boolean parseComplexCurrency, int type) {

        int position = parsePosition.getIndex();
        int oldStart = parsePosition.getIndex();

        // Match padding before prefix
        if (formatWidth > 0 && padPosition == PAD_BEFORE_PREFIX) {
            position = skipPadding(text, position);
        }

        // Match positive and negative prefixes; prefer longest match.
        int posMatch = compareAffix(text, position, false, true, posPrefix, parseComplexCurrency, type, currency);
        int negMatch = compareAffix(text, position, true, true, negPrefix, parseComplexCurrency, type, currency);
        if (posMatch >= 0 && negMatch >= 0) {
            if (posMatch > negMatch) {
                negMatch = -1;
            } else if (negMatch > posMatch) {
                posMatch = -1;
            }
        }
        if (posMatch >= 0) {
            position += posMatch;
        } else if (negMatch >= 0) {
            position += negMatch;
        } else {
            parsePosition.setErrorIndex(position);
            return false;
        }

        // Match padding after prefix
        if (formatWidth > 0 && padPosition == PAD_AFTER_PREFIX) {
            position = skipPadding(text, position);
        }

        // process digits or Inf, find decimal position
        status[STATUS_INFINITE] = false;
        if (text.regionMatches(position, symbols.getInfinity(), 0,
                                              symbols.getInfinity().length())) {
            position += symbols.getInfinity().length();
            status[STATUS_INFINITE] = true;
        } else {
            // We now have a string of digits, possibly with grouping symbols, and decimal
            // points. We want to process these into a DigitList.  We don't want to put a
            // bunch of leading zeros into the DigitList though, so we keep track of the
            // location of the decimal point, put only significant digits into the
            // DigitList, and adjust the exponent as needed.

            digits.decimalAt = digits.count = 0;
            char [] digitSymbols = symbols.getDigitsLocal();
            char decimal = (currencySignCount == CURRENCY_SIGN_COUNT_ZERO) ?
                    symbols.getDecimalSeparator() : symbols.getMonetaryDecimalSeparator();
            char grouping = (currencySignCount == CURRENCY_SIGN_COUNT_ZERO) ?
                    symbols.getGroupingSeparator() : symbols.getMonetaryGroupingSeparator();

            String exponentSep = symbols.getExponentSeparator();
            boolean sawDecimal = false;
            boolean sawGrouping = false;
            boolean sawExponent = false;
            boolean sawDigit = false;
            long exponent = 0; // Set to the exponent value, if any
            int digit = 0;

            // strict parsing
            boolean strictParse = isParseStrict();
            boolean strictFail = false; // did we exit with a strict parse failure?
            int lastGroup = -1; // where did we last see a grouping separator?
            int digitStart = position; // where did the digit start?
            int gs2 = groupingSize2 == 0 ? groupingSize : groupingSize2;

            // equivalent grouping and decimal support
            boolean skipExtendedSeparatorParsing = ICUConfig.get(
                "com.ibm.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", "false")
                .equals("true");

            UnicodeSet decimalEquiv = skipExtendedSeparatorParsing ? UnicodeSet.EMPTY :
                getEquivalentDecimals(decimal, strictParse);
            UnicodeSet groupEquiv = skipExtendedSeparatorParsing ? UnicodeSet.EMPTY :
                (strictParse ? strictDefaultGroupingSeparators : defaultGroupingSeparators);

            // We have to track digitCount ourselves, because digits.count will pin when
            // the maximum allowable digits is reached.
            int digitCount = 0;

            int backup = -1;
            int ch;
            for (; position < text.length(); position += UTF16.getCharCount(ch)) {
                ch = UTF16.charAt(text,position);


                // We recognize all digit ranges, not only the Latin digit range
                // '0'..'9'. We do so by using the UCharacter.digit() method, which
                // converts a valid Unicode digit to the range 0..9.
                //
                // The character 'ch' may be a digit. If so, place its value from 0 to 9
                // in 'digit'. First try using the locale digit, which may or MAY NOT be a
                // standard Unicode digit range. If this fails, try using the standard
                // Unicode digit ranges by calling UCharacter.digit(). If this also fails,
                // digit will have a value outside the range 0..9.
                digit = ch - digitSymbols[0];
                if (digit < 0 || digit > 9)
                    digit = UCharacter.digit(ch, 10);
                if (digit < 0 || digit > 9) {
                    for ( digit = 0 ; digit < 10 ; digit++) {
                        if ( ch == digitSymbols[digit] )
                            break;
                    }
                }



                if (digit == 0) {
                    // Cancel out backup setting (see grouping handler below)
                    if (strictParse && backup != -1) {
                        // comma followed by digit, so group before comma is a secondary
                        // group. If there was a group separator before that, the group
                        // must == the secondary group length, else it can be <= the the
                        // secondary group length.
                        if ((lastGroup != -1 && countCodePoints(text, lastGroup, backup) - 1 != gs2)
                                || (lastGroup == -1 && countCodePoints(text, digitStart, position) - 1 > gs2)) {
                            strictFail = true;
                            break;
                        }
                        lastGroup = backup;
                    }
                    backup = -1; // Do this BEFORE continue statement below!!!
                    sawDigit = true;

                    // Handle leading zeros
                    if (digits.count == 0) {
                        if (!sawDecimal) {
                            // Ignore leading zeros in integer part of number.
                            continue;
                        }

                        // If we have seen the decimal, but no significant digits yet,
                        // then we account for leading zeros by decrementing the
                        // digits.decimalAt into negative values.
                        --digits.decimalAt;
                    } else {
                        ++digitCount;
                        digits.append((char) (digit + '0'));
                    }
                } else if (digit > 0 && digit <= 9) // [sic] digit==0 handled above
                {
                    if (strictParse) {
                        if (backup != -1) {
                            if ((lastGroup != -1 && countCodePoints(text, lastGroup, backup) - 1 != gs2)
                                    || (lastGroup == -1 && countCodePoints(text, digitStart, position) - 1 > gs2)) {
                                strictFail = true;
                                break;
                            }
                            lastGroup = backup;
                        }
                    }

                    sawDigit = true;
                    ++digitCount;
                    digits.append((char) (digit + '0'));

                    // Cancel out backup setting (see grouping handler below)
                    backup = -1;
                } else if (ch == decimal) {
                    if (strictParse) {
                        if (backup != -1 ||
                            (lastGroup != -1 && countCodePoints(text,lastGroup,position) != groupingSize + 1)) {
                            strictFail = true;
                            break;
                        }
                    }
                    // If we're only parsing integers, or if we ALREADY saw the decimal,
                    // then don't parse this one.
                    if (isParseIntegerOnly() || sawDecimal) {
                        break;
                    }
                    digits.decimalAt = digitCount; // Not digits.count!
                    sawDecimal = true;
                } else if (isGroupingUsed() && ch == grouping) {
                    if (sawDecimal) {
                        break;
                    }
                    if (strictParse) {
                        if ((!sawDigit || backup != -1)) {
                            // leading group, or two group separators in a row
                            strictFail = true;
                            break;
                        }
                    }
                    // Ignore grouping characters, if we are using them, but require that
                    // they be followed by a digit. Otherwise we backup and reprocess
                    // them.
                    backup = position;
                    sawGrouping = true;
                } else if (!sawDecimal && decimalEquiv.contains(ch)) {
                    if (strictParse) {
                        if (backup != -1 ||
                            (lastGroup != -1 && countCodePoints(text,lastGroup,position) != groupingSize + 1)) {
                            strictFail = true;
                            break;
                        }
                    }
                    // If we're only parsing integers, then don't parse this one.
                    if (isParseIntegerOnly())
                        break;
                    digits.decimalAt = digitCount; // Not digits.count!

                    // Once we see a decimal separator character, we only accept that
                    // decimal separator character from then on.
                    decimal = (char) ch;
                    sawDecimal = true;
                } else if (isGroupingUsed() && !sawGrouping && groupEquiv.contains(ch)) {
                    if (sawDecimal) {
                        break;
                    }
                    if (strictParse) {
                        if ((!sawDigit || backup != -1)) {
                            // leading group, or two group separators in a row
                            strictFail = true;
                            break;
                        }
                    }
                    // Once we see a grouping character, we only accept that grouping
                    // character from then on.
                    grouping = (char) ch;

                    // Ignore grouping characters, if we are using them, but require that
                    // they be followed by a digit. Otherwise we backup and reprocess
                    // them.
                    backup = position;
                    sawGrouping = true;
                } else if (!sawExponent && text.regionMatches(true, position, exponentSep, 0, exponentSep.length())) {
                    // Parse sign, if present
                    boolean negExp = false;
                    int pos = position + exponentSep.length();
                    if (pos < text.length()) {
                        ch = UTF16.charAt(text,pos);
                        if (ch == symbols.getPlusSign()) {
                            ++pos;
                        } else if (ch == symbols.getMinusSign()) {
                            ++pos;
                            negExp = true;
                        }
                    }

                    DigitList exponentDigits = new DigitList();
                    exponentDigits.count = 0;
                    while (pos < text.length()) {
                        digit = UTF16.charAt(text,pos) - digitSymbols[0];
                        if (digit < 0 || digit > 9) {
                            // Can't parse "[1E0]" when pattern is "0.###E0;[0.###E0]"
                            // Should update reassign the value of 'ch' in the code: digit
                            // = Character.digit(ch, 10); [Richard/GCL]
                            digit = UCharacter.digit(UTF16.charAt(text,pos), 10);
                        }
                        if (digit >= 0 && digit <= 9) {
                            exponentDigits.append((char) (digit + '0'));
                            pos += UTF16.getCharCount(UTF16.charAt(text,pos));
                        } else {
                            break;
                        }
                    }

                    if (exponentDigits.count > 0) {
                        // defer strict parse until we know we have a bona-fide exponent
                        if (strictParse) {
                            if (backup != -1 || lastGroup != -1) {
                                strictFail = true;
                                break;
                            }
                        }

                        // Quick overflow check for exponential part.  Actual limit check
                        // will be done later in this code.
                        if (exponentDigits.count > 10 /* maximum decimal digits for int */) {
                            if (negExp) {
                                // set underflow flag
                                status[STATUS_UNDERFLOW] = true;
                            } else {
                                // set infinite flag
                                status[STATUS_INFINITE] = true;
                            }
                        } else {
                            exponentDigits.decimalAt = exponentDigits.count;
                            exponent = exponentDigits.getLong();
                            if (negExp) {
                                exponent = -exponent;
                            }
                        }
                        position = pos; // Advance past the exponent
                        sawExponent = true;
                    }

                    break; // Whether we fail or succeed, we exit this loop
                } else {
                    break;
                }
            }

            if (backup != -1)
                position = backup;

            // If there was no decimal point we have an integer
            if (!sawDecimal)
                digits.decimalAt = digitCount; // Not digits.count!

            // check for strict parse errors
            if (strictParse && !sawDecimal) {
                if (lastGroup != -1 && countCodePoints(text,lastGroup,position) != groupingSize + 1) {
                    strictFail = true;
                }
            }
            if (strictFail) {
                // only set with strictParse and a leading zero error leading zeros are an
                // error with strict parsing except immediately before nondigit (except
                // group separator followed by digit), or end of text.

                parsePosition.setIndex(oldStart);
                parsePosition.setErrorIndex(position);
                return false;
            }

            // Adjust for exponent, if any
            exponent += digits.decimalAt;
            if (exponent < -getParseMaxDigits()) {
                status[STATUS_UNDERFLOW] = true;
            } else if (exponent > getParseMaxDigits()) {
                status[STATUS_INFINITE] = true;
            } else {
                digits.decimalAt = (int) exponent;
            }

            // If none of the text string was recognized. For example, parse "x" with
            // pattern "#0.00" (return index and error index both 0) parse "$" with
            // pattern "$#0.00". (return index 0 and error index 1).
            if (!sawDigit && digitCount == 0) {
                parsePosition.setIndex(oldStart);
                parsePosition.setErrorIndex(oldStart);
                return false;
            }
        }

        // Match padding before suffix
        if (formatWidth > 0 && padPosition == PAD_BEFORE_SUFFIX) {
            position = skipPadding(text, position);
        }

        // Match positive and negative suffixes; prefer longest match.
        if (posMatch >= 0) {
            posMatch = compareAffix(text, position, false, false, posSuffix, parseComplexCurrency, type, currency);
        }
        if (negMatch >= 0) {
            negMatch = compareAffix(text, position, true, false, negSuffix, parseComplexCurrency, type, currency);
        }
        if (posMatch >= 0 && negMatch >= 0) {
            if (posMatch > negMatch) {
                negMatch = -1;
            } else if (negMatch > posMatch) {
                posMatch = -1;
            }
        }

        // Fail if neither or both
        if ((posMatch >= 0) == (negMatch >= 0)) {
            parsePosition.setErrorIndex(position);
            return false;
        }

        position += (posMatch >= 0 ? posMatch : negMatch);

        // Match padding after suffix
        if (formatWidth > 0 && padPosition == PAD_AFTER_SUFFIX) {
            position = skipPadding(text, position);
        }

        parsePosition.setIndex(position);

        status[STATUS_POSITIVE] = (posMatch >= 0);

        if (parsePosition.getIndex() == oldStart) {
            parsePosition.setErrorIndex(position);
            return false;
        }
        return true;
    }

    // Utility method used to count the number of codepoints
    private int countCodePoints(String str,int start, int end) {
        int count = 0;
        int index = start;
        while ( index < end ) {
            count++;
            index += UTF16.getCharCount(UTF16.charAt(str, index));
        }
        return count;
    }
    /**
     * Returns a set of characters equivalent to the given desimal separator used for
     * parsing number.  This method may return an empty set.
     */
    private UnicodeSet getEquivalentDecimals(char decimal, boolean strictParse) {
        UnicodeSet equivSet = UnicodeSet.EMPTY;
        if (strictParse) {
            if (strictDotEquivalents.contains(decimal)) {
                equivSet = strictDotEquivalents;
            } else if (strictCommaEquivalents.contains(decimal)) {
                equivSet = strictCommaEquivalents;
            }
        } else {
            if (dotEquivalents.contains(decimal)) {
                equivSet = dotEquivalents;
            } else if (commaEquivalents.contains(decimal)) {
                equivSet = commaEquivalents;
            }
        }
        return equivSet;
    }

    /**
     * Starting at position, advance past a run of pad characters, if any. Return the
     * index of the first character after position that is not a pad character. Result is
     * >= position.
     */
    private final int skipPadding(String text, int position) {
        while (position < text.length() && text.charAt(position) == pad) {
            ++position;
        }
        return position;
    }

    /**
     * Returns the length matched by the given affix, or -1 if none. Runs of white space
     * in the affix, match runs of white space in the input. Pattern white space and input
     * white space are determined differently; see code.
     *
     * @param text input text
     * @param pos offset into input at which to begin matching
     * @param isNegative
     * @param isPrefix
     * @param affixPat affix pattern used for currency affix comparison
     * @param copmplexCurrencyParsing whether it is currency parsing or not
     * @param type compare against currency type, LONG_NAME only or not.
     * @param currency return value for parsed currency, for generic currency parsing
     * mode, or null for normal parsing.  In generic currency parsing mode, any currency
     * is parsed, not just the currency that this formatter is set to.
     * @return length of input that matches, or -1 if match failure
     */
    private int compareAffix(String text, int pos, boolean isNegative, boolean isPrefix,
                             String affixPat, boolean complexCurrencyParsing, int type, Currency[] currency) {
        if (currency != null || currencyChoice != null || (currencySignCount != CURRENCY_SIGN_COUNT_ZERO && complexCurrencyParsing)) {
            return compareComplexAffix(affixPat, text, pos, type, currency);
        }
        if (isPrefix) {
            return compareSimpleAffix(isNegative ? negativePrefix : positivePrefix, text, pos);
        } else {
            return compareSimpleAffix(isNegative ? negativeSuffix : positiveSuffix, text, pos);
        }

    }

    /**
     * Check for bidi marks: LRM, RLM, ALM
     */
    private static boolean isBidiMark(int c) {
        return (c==0x200E || c==0x200F || c==0x061C);
    }

    /**
     * Remove bidi marks from affix
     */
    private static final int TRIM_BUFLEN = 32;
    private static String trimMarksFromAffix(String affix) { 
        boolean hasBidiMark = false; 
        int idx = 0; 
        for (; idx < affix.length(); idx++) { 
            if (isBidiMark(affix.charAt(idx))) { 
                hasBidiMark = true; 
                break; 
            } 
        } 
        if (!hasBidiMark) { 
            return affix; 
        } 

        StringBuilder buf = new StringBuilder(); 
        buf.append(affix, 0, idx); 
        idx++;  // skip the first Bidi mark 
        for (; idx < affix.length(); idx++) { 
            char c = affix.charAt(idx); 
            if (!isBidiMark(c)) { 
                buf.append(c); 
            } 
        } 

        return buf.toString(); 
    } 

    /**
     * Return the length matched by the given affix, or -1 if none. Runs of white space in
     * the affix, match runs of white space in the input. Pattern white space and input
     * white space are determined differently; see code.
     *
     * @param affix pattern string, taken as a literal
     * @param input input text
     * @param pos offset into input at which to begin matching
     * @return length of input that matches, or -1 if match failure
     */
    private static int compareSimpleAffix(String affix, String input, int pos) {
        int start = pos;
        // Affixes here might consist of sign, currency symbol and related spacing, etc.
        // For more efficiency we should keep lazily-created trimmed affixes around in
        // instance variables instead of trimming each time they are used (the next step).
        String trimmedAffix = (affix.length() > 1)? trimMarksFromAffix(affix): affix;
        for (int i = 0; i < trimmedAffix.length();) {
            int c = UTF16.charAt(trimmedAffix, i);
            int len = UTF16.getCharCount(c);
            if (PatternProps.isWhiteSpace(c)) {
                // We may have a pattern like: \u200F and input text like: \u200F Note
                // that U+200F and U+0020 are Pattern_White_Space but only U+0020 is
                // UWhiteSpace. So we have to first do a direct match of the run of RULE
                // whitespace in the pattern, then match any extra characters.
                boolean literalMatch = false;
                while (pos < input.length()) {
                    int ic = UTF16.charAt(input, pos);
                    if (ic == c) {
                        literalMatch = true;
                        i += len;
                        pos += len;
                        if (i == trimmedAffix.length()) {
                            break;
                        }
                        c = UTF16.charAt(trimmedAffix, i);
                        len = UTF16.getCharCount(c);
                        if (!PatternProps.isWhiteSpace(c)) {
                            break;
                        }
                    } else if (isBidiMark(ic)) {
                        pos++; // just skip over this input text
                    } else {
                        break;
                    }
                }

                // Advance over run in trimmedAffix
                i = skipPatternWhiteSpace(trimmedAffix, i);

                // Advance over run in input text. Must see at least one white space char
                // in input, unless we've already matched some characters literally.
                int s = pos;
                pos = skipUWhiteSpace(input, pos);
                if (pos == s && !literalMatch) {
                    return -1;
                }
                // If we skip UWhiteSpace in the input text, we need to skip it in the
                // pattern.  Otherwise, the previous lines may have skipped over text
                // (such as U+00A0) that is also in the trimmedAffix.
                i = skipUWhiteSpace(trimmedAffix, i);
            } else {
                boolean match = false;
                while (pos < input.length()) {
                    int ic = UTF16.charAt(input, pos);
                    if (!match && equalWithSignCompatibility(ic, c)) {
                        i += len;
                        pos += len;
                        match = true;
                    } else if (isBidiMark(ic)) {
                        pos++; // just skip over this input text
                    } else {
                        break;
                    }
                }
                if (!match) {
                    return -1;
                }
            }
        }
        return pos - start;
    }

    private static boolean equalWithSignCompatibility(int lhs, int rhs) {
        return lhs == rhs
                || (minusSigns.contains(lhs) && minusSigns.contains(rhs))
                || (plusSigns.contains(lhs) && plusSigns.contains(rhs));
    }

    /**
     * Skips over a run of zero or more Pattern_White_Space characters at pos in text.
     */
    private static int skipPatternWhiteSpace(String text, int pos) {
        while (pos < text.length()) {
            int c = UTF16.charAt(text, pos);
            if (!PatternProps.isWhiteSpace(c)) {
                break;
            }
            pos += UTF16.getCharCount(c);
        }
        return pos;
    }

    /**
     * Skips over a run of zero or more isUWhiteSpace() characters at pos in text.
     */
    private static int skipUWhiteSpace(String text, int pos) {
        while (pos < text.length()) {
            int c = UTF16.charAt(text, pos);
            if (!UCharacter.isUWhiteSpace(c)) {
                break;
            }
            pos += UTF16.getCharCount(c);
        }
        return pos;
    }

     /**
     * Skips over a run of zero or more bidi marks at pos in text.
     */
    private static int skipBidiMarks(String text, int pos) {
        while (pos < text.length()) {
            int c = UTF16.charAt(text, pos);
            if (!isBidiMark(c)) {
                break;
            }
            pos += UTF16.getCharCount(c);
        }
        return pos;
    }

   /**
     * Returns the length matched by the given affix, or -1 if none.
     *
     * @param affixPat pattern string
     * @param text input text
     * @param pos offset into input at which to begin matching
     * @param type parse against currency type, LONG_NAME only or not.
     * @param currency return value for parsed currency, for generic
     * currency parsing mode, or null for normal parsing.  In generic
     * currency parsing mode, any currency is parsed, not just the
     * currency that this formatter is set to.
     * @return position after the matched text, or -1 if match failure
     */
    private int compareComplexAffix(String affixPat, String text, int pos, int type,
                                    Currency[] currency) {
        int start = pos;
        for (int i = 0; i < affixPat.length() && pos >= 0;) {
            char c = affixPat.charAt(i++);
            if (c == QUOTE) {
                for (;;) {
                    int j = affixPat.indexOf(QUOTE, i);
                    if (j == i) {
                        pos = match(text, pos, QUOTE);
                        i = j + 1;
                        break;
                    } else if (j > i) {
                        pos = match(text, pos, affixPat.substring(i, j));
                        i = j + 1;
                        if (i < affixPat.length() && affixPat.charAt(i) == QUOTE) {
                            pos = match(text, pos, QUOTE);
                            ++i;
                            // loop again
                        } else {
                            break;
                        }
                    } else {
                        // Unterminated quote; should be caught by apply
                        // pattern.
                        throw new RuntimeException();
                    }
                }
                continue;
            }

            switch (c) {
            case CURRENCY_SIGN:
                // since the currency names in choice format is saved the same way as
                // other currency names, do not need to do currency choice parsing here.
                // the general currency parsing parse against all names, including names
                // in choice format.  assert(currency != null || (getCurrency() != null &&
                // currencyChoice != null));
                boolean intl = i < affixPat.length() && affixPat.charAt(i) == CURRENCY_SIGN;
                if (intl) {
                    ++i;
                }
                boolean plural = i < affixPat.length() && affixPat.charAt(i) == CURRENCY_SIGN;
                if (plural) {
                    ++i;
                    intl = false;
                }
                // Parse generic currency -- anything for which we have a display name, or
                // any 3-letter ISO code.  Try to parse display name for our locale; first
                // determine our locale.  TODO: use locale in CurrencyPluralInfo
                ULocale uloc = getLocale(ULocale.VALID_LOCALE);
                if (uloc == null) {
                    // applyPattern has been called; use the symbols
                    uloc = symbols.getLocale(ULocale.VALID_LOCALE);
                }
                // Delegate parse of display name => ISO code to Currency
                ParsePosition ppos = new ParsePosition(pos);
                // using Currency.parse to handle mixed style parsing.
                String iso = Currency.parse(uloc, text, type, ppos);

                // If parse succeeds, populate currency[0]
                if (iso != null) {
                    if (currency != null) {
                        currency[0] = Currency.getInstance(iso);
                    } else {
                        // The formatter is currency-style but the client has not requested
                        // the value of the parsed currency. In this case, if that value does
                        // not match the formatter's current value, then the parse fails.
                        Currency effectiveCurr = getEffectiveCurrency();
                        if (iso.compareTo(effectiveCurr.getCurrencyCode()) != 0) {
                            pos = -1;
                            continue;
                        }
                    }
                    pos = ppos.getIndex();
                } else {
                    pos = -1;
                }
                continue;
            case PATTERN_PERCENT:
                c = symbols.getPercent();
                break;
            case PATTERN_PER_MILLE:
                c = symbols.getPerMill();
                break;
            case PATTERN_MINUS:
                c = symbols.getMinusSign();
                break;
            }
            pos = match(text, pos, c);
            if (PatternProps.isWhiteSpace(c)) {
                i = skipPatternWhiteSpace(affixPat, i);
            }
        }

        return pos - start;
    }

    /**
     * Matches a single character at text[pos] and return the index of the next character
     * upon success. Return -1 on failure. If ch is a Pattern_White_Space then match a run of
     * white space in text.
     */
    static final int match(String text, int pos, int ch) {
        if (pos < 0 || pos >= text.length()) {
            return -1;
        }
        pos = skipBidiMarks(text, pos);
        if (PatternProps.isWhiteSpace(ch)) {
            // Advance over run of white space in input text
            // Must see at least one white space char in input
            int s = pos;
            pos = skipPatternWhiteSpace(text, pos);
            if (pos == s) {
                return -1;
            }
            return pos;
        }
        if (pos >= text.length() || UTF16.charAt(text, pos) != ch) {
            return -1;
        }
        pos = skipBidiMarks(text, pos + UTF16.getCharCount(ch));
        return pos;
    }

    /**
     * Matches a string at text[pos] and return the index of the next character upon
     * success. Return -1 on failure. Match a run of white space in str with a run of
     * white space in text.
     */
    static final int match(String text, int pos, String str) {
        for (int i = 0; i < str.length() && pos >= 0;) {
            int ch = UTF16.charAt(str, i);
            i += UTF16.getCharCount(ch);
            pos = match(text, pos, ch);
            if (PatternProps.isWhiteSpace(ch)) {
                i = skipPatternWhiteSpace(str, i);
            }
        }
        return pos;
    }

    /**
     * Returns a copy of the decimal format symbols used by this format.
     *
     * @return desired DecimalFormatSymbols
     * @see DecimalFormatSymbols
     * @stable ICU 2.0
     */
    public DecimalFormatSymbols getDecimalFormatSymbols() {
        try {
            // don't allow multiple references
            return (DecimalFormatSymbols) symbols.clone();
        } catch (Exception foo) {
            return null; // should never happen
        }
    }

    /**
     * Sets the decimal format symbols used by this format. The format uses a copy of the
     * provided symbols.
     *
     * @param newSymbols desired DecimalFormatSymbols
     * @see DecimalFormatSymbols
     * @stable ICU 2.0
     */
    public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
        symbols = (DecimalFormatSymbols) newSymbols.clone();
        setCurrencyForSymbols();
        expandAffixes(null);
    }

    /**
     * Update the currency object to match the symbols. This method is used only when the
     * caller has passed in a symbols object that may not be the default object for its
     * locale.
     */
    private void setCurrencyForSymbols() {

        // Bug 4212072 Update the affix strings according to symbols in order to keep the
        // affix strings up to date.  [Richard/GCL]

        // With the introduction of the Currency object, the currency symbols in the DFS
        // object are ignored. For backward compatibility, we check any explicitly set DFS
        // object. If it is a default symbols object for its locale, we change the
        // currency object to one for that locale. If it is custom, we set the currency to
        // null.
        DecimalFormatSymbols def = new DecimalFormatSymbols(symbols.getULocale());

        if (symbols.getCurrencySymbol().equals(def.getCurrencySymbol())
                && symbols.getInternationalCurrencySymbol()
                       .equals(def.getInternationalCurrencySymbol())) {
            setCurrency(Currency.getInstance(symbols.getULocale()));
        } else {
            setCurrency(null);
        }
    }

    /**
     * Returns the positive prefix.
     *
     * <p>Examples: +123, $123, sFr123
     * @return the prefix
     * @stable ICU 2.0
     */
    public String getPositivePrefix() {
        return positivePrefix;
    }

    /**
     * Sets the positive prefix.
     *
     * <p>Examples: +123, $123, sFr123
     * @param newValue the prefix
     * @stable ICU 2.0
     */
    public void setPositivePrefix(String newValue) {
        positivePrefix = newValue;
        posPrefixPattern = null;
    }

    /**
     * Returns the negative prefix.
     *
     * <p>Examples: -123, ($123) (with negative suffix), sFr-123
     *
     * @return the prefix
     * @stable ICU 2.0
     */
    public String getNegativePrefix() {
        return negativePrefix;
    }

    /**
     * Sets the negative prefix.
     *
     * <p>Examples: -123, ($123) (with negative suffix), sFr-123
     * @param newValue the prefix
     * @stable ICU 2.0
     */
    public void setNegativePrefix(String newValue) {
        negativePrefix = newValue;
        negPrefixPattern = null;
    }

    /**
     * Returns the positive suffix.
     *
     * <p>Example: 123%
     *
     * @return the suffix
     * @stable ICU 2.0
     */
    public String getPositiveSuffix() {
        return positiveSuffix;
    }

    /**
     * Sets the positive suffix.
     *
     * <p>Example: 123%
     * @param newValue the suffix
     * @stable ICU 2.0
     */
    public void setPositiveSuffix(String newValue) {
        positiveSuffix = newValue;
        posSuffixPattern = null;
    }

    /**
     * Returns the negative suffix.
     *
     * <p>Examples: -123%, ($123) (with positive suffixes)
     *
     * @return the suffix
     * @stable ICU 2.0
     */
    public String getNegativeSuffix() {
        return negativeSuffix;
    }

    /**
     * Sets the positive suffix.
     *
     * <p>Examples: 123%
     * @param newValue the suffix
     * @stable ICU 2.0
     */
    public void setNegativeSuffix(String newValue) {
        negativeSuffix = newValue;
        negSuffixPattern = null;
    }

    /**
     * Returns the multiplier for use in percent, permill, etc. For a percentage, set the
     * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent
     * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be
     * 1000.
     *
     * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
     *
     * @return the multiplier
     * @stable ICU 2.0
     */
    public int getMultiplier() {
        return multiplier;
    }

    /**
     * Sets the multiplier for use in percent, permill, etc. For a percentage, set the
     * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent
     * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be
     * 1000.
     *
     * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
     *
     * @param newValue the multiplier
     * @stable ICU 2.0
     */
    public void setMultiplier(int newValue) {
        if (newValue == 0) {
            throw new IllegalArgumentException("Bad multiplier: " + newValue);
        }
        multiplier = newValue;
    }

    /**
     * {@icu} Returns the rounding increment.
     *
     * @return A positive rounding increment, or <code>null</code> if a custom rounding
     * increment is not in effect.
     * @see #setRoundingIncrement
     * @see #getRoundingMode
     * @see #setRoundingMode
     * @stable ICU 2.0
     */
    public java.math.BigDecimal getRoundingIncrement() {
        if (roundingIncrementICU == null)
            return null;
        return roundingIncrementICU.toBigDecimal();
    }

    /**
     * {@icu} Sets the rounding increment. In the absence of a rounding increment, numbers
     * will be rounded to the number of digits displayed.
     *
     * @param newValue A positive rounding increment, or <code>null</code> or
     * <code>BigDecimal(0.0)</code> to use the default rounding increment.
     * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
     * @see #getRoundingIncrement
     * @see #getRoundingMode
     * @see #setRoundingMode
     * @stable ICU 2.0
     */
    public void setRoundingIncrement(java.math.BigDecimal newValue) {
        if (newValue == null) {
            setRoundingIncrement((BigDecimal) null);
        } else {
            setRoundingIncrement(new BigDecimal(newValue));
        }
    }

    /**
     * {@icu} Sets the rounding increment. In the absence of a rounding increment, numbers
     * will be rounded to the number of digits displayed.
     *
     * @param newValue A positive rounding increment, or <code>null</code> or
     * <code>BigDecimal(0.0)</code> to use the default rounding increment.
     * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
     * @see #getRoundingIncrement
     * @see #getRoundingMode
     * @see #setRoundingMode
     * @stable ICU 3.6
     */
    public void setRoundingIncrement(BigDecimal newValue) {
        int i = newValue == null ? 0 : newValue.compareTo(BigDecimal.ZERO);
        if (i < 0) {
            throw new IllegalArgumentException("Illegal rounding increment");
        }
        if (i == 0) {
            setInternalRoundingIncrement(null);
        } else {
            setInternalRoundingIncrement(newValue);
        }
        resetActualRounding();
    }

    /**
     * {@icu} Sets the rounding increment. In the absence of a rounding increment, numbers
     * will be rounded to the number of digits displayed.
     *
     * @param newValue A positive rounding increment, or 0.0 to use the default
     * rounding increment.
     * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
     * @see #getRoundingIncrement
     * @see #getRoundingMode
     * @see #setRoundingMode
     * @stable ICU 2.0
     */
    public void setRoundingIncrement(double newValue) {
        if (newValue < 0.0) {
            throw new IllegalArgumentException("Illegal rounding increment");
        }
        if (newValue == 0.0d) {
            setInternalRoundingIncrement((BigDecimal) null);
        } else {
            // Should use BigDecimal#valueOf(double) instead of constructor
            // to avoid the double precision problem.
            setInternalRoundingIncrement(BigDecimal.valueOf(newValue));
        }
        resetActualRounding();
    }

    /**
     * Returns the rounding mode.
     *
     * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
     * @see #setRoundingIncrement
     * @see #getRoundingIncrement
     * @see #setRoundingMode
     * @see java.math.BigDecimal
     * @stable ICU 2.0
     */
    @Override
    public int getRoundingMode() {
        return roundingMode;
    }

    /**
     * Sets the rounding mode. This has no effect unless the rounding increment is greater
     * than zero.
     *
     * @param roundingMode A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
     * @exception IllegalArgumentException if <code>roundingMode</code> is unrecognized.
     * @see #setRoundingIncrement
     * @see #getRoundingIncrement
     * @see #getRoundingMode
     * @see java.math.BigDecimal
     * @stable ICU 2.0
     */
    @Override
    public void setRoundingMode(int roundingMode) {
        if (roundingMode < BigDecimal.ROUND_UP || roundingMode > BigDecimal.ROUND_UNNECESSARY) {
            throw new IllegalArgumentException("Invalid rounding mode: " + roundingMode);
        }

        this.roundingMode = roundingMode;
        resetActualRounding();
    }

    /**
     * Returns the width to which the output of <code>format()</code> is padded. The width is
     * counted in 16-bit code units.
     *
     * @return the format width, or zero if no padding is in effect
     * @see #setFormatWidth
     * @see #getPadCharacter
     * @see #setPadCharacter
     * @see #getPadPosition
     * @see #setPadPosition
     * @stable ICU 2.0
     */
    public int getFormatWidth() {
        return formatWidth;
    }

    /**
     * Sets the width to which the output of <code>format()</code> is
     * padded. The width is counted in 16-bit code units.  This method
     * also controls whether padding is enabled.
     *
     * @param width the width to which to pad the result of
     * <code>format()</code>, or zero to disable padding
     * @exception IllegalArgumentException if <code>width</code> is < 0
     * @see #getFormatWidth
     * @see #getPadCharacter
     * @see #setPadCharacter
     * @see #getPadPosition
     * @see #setPadPosition
     * @stable ICU 2.0
     */
    public void setFormatWidth(int width) {
        if (width < 0) {
            throw new IllegalArgumentException("Illegal format width");
        }
        formatWidth = width;
    }

    /**
     * {@icu} Returns the character used to pad to the format width. The default is ' '.
     *
     * @return the pad character
     * @see #setFormatWidth
     * @see #getFormatWidth
     * @see #setPadCharacter
     * @see #getPadPosition
     * @see #setPadPosition
     * @stable ICU 2.0
     */
    public char getPadCharacter() {
        return pad;
    }

    /**
     * {@icu} Sets the character used to pad to the format width. If padding is not
     * enabled, then this will take effect if padding is later enabled.
     *
     * @param padChar the pad character
     * @see #setFormatWidth
     * @see #getFormatWidth
     * @see #getPadCharacter
     * @see #getPadPosition
     * @see #setPadPosition
     * @stable ICU 2.0
     */
    public void setPadCharacter(char padChar) {
        pad = padChar;
    }

    /**
     * {@icu} Returns the position at which padding will take place. This is the location at
     * which padding will be inserted if the result of <code>format()</code> is shorter
     * than the format width.
     *
     * @return the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
     *         <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
     *         <code>PAD_AFTER_SUFFIX</code>.
     * @see #setFormatWidth
     * @see #getFormatWidth
     * @see #setPadCharacter
     * @see #getPadCharacter
     * @see #setPadPosition
     * @see #PAD_BEFORE_PREFIX
     * @see #PAD_AFTER_PREFIX
     * @see #PAD_BEFORE_SUFFIX
     * @see #PAD_AFTER_SUFFIX
     * @stable ICU 2.0
     */
    public int getPadPosition() {
        return padPosition;
    }

    /**
     * {@icu} Sets the position at which padding will take place. This is the location at
     * which padding will be inserted if the result of <code>format()</code> is shorter
     * than the format width. This has no effect unless padding is enabled.
     *
     * @param padPos the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
     * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
     * <code>PAD_AFTER_SUFFIX</code>.
     * @exception IllegalArgumentException if the pad position in unrecognized
     * @see #setFormatWidth
     * @see #getFormatWidth
     * @see #setPadCharacter
     * @see #getPadCharacter
     * @see #getPadPosition
     * @see #PAD_BEFORE_PREFIX
     * @see #PAD_AFTER_PREFIX
     * @see #PAD_BEFORE_SUFFIX
     * @see #PAD_AFTER_SUFFIX
     * @stable ICU 2.0
     */
    public void setPadPosition(int padPos) {
        if (padPos < PAD_BEFORE_PREFIX || padPos > PAD_AFTER_SUFFIX) {
            throw new IllegalArgumentException("Illegal pad position");
        }
        padPosition = padPos;
    }

    /**
     * {@icu} Returns whether or not scientific notation is used.
     *
     * @return true if this object formats and parses scientific notation
     * @see #setScientificNotation
     * @see #getMinimumExponentDigits
     * @see #setMinimumExponentDigits
     * @see #isExponentSignAlwaysShown
     * @see #setExponentSignAlwaysShown
     * @stable ICU 2.0
     */
    public boolean isScientificNotation() {
        return useExponentialNotation;
    }

    /**
     * {@icu} Sets whether or not scientific notation is used. When scientific notation is
     * used, the effective maximum number of integer digits is <= 8. If the maximum number
     * of integer digits is set to more than 8, the effective maximum will be 1. This
     * allows this call to generate a 'default' scientific number format without
     * additional changes.
     *
     * @param useScientific true if this object formats and parses scientific notation
     * @see #isScientificNotation
     * @see #getMinimumExponentDigits
     * @see #setMinimumExponentDigits
     * @see #isExponentSignAlwaysShown
     * @see #setExponentSignAlwaysShown
     * @stable ICU 2.0
     */
    public void setScientificNotation(boolean useScientific) {
        useExponentialNotation = useScientific;
    }

    /**
     * {@icu} Returns the minimum exponent digits that will be shown.
     *
     * @return the minimum exponent digits that will be shown
     * @see #setScientificNotation
     * @see #isScientificNotation
     * @see #setMinimumExponentDigits
     * @see #isExponentSignAlwaysShown
     * @see #setExponentSignAlwaysShown
     * @stable ICU 2.0
     */
    public byte getMinimumExponentDigits() {
        return minExponentDigits;
    }

    /**
     * {@icu} Sets the minimum exponent digits that will be shown. This has no effect
     * unless scientific notation is in use.
     *
     * @param minExpDig a value >= 1 indicating the fewest exponent
     * digits that will be shown
     * @exception IllegalArgumentException if <code>minExpDig</code> < 1
     * @see #setScientificNotation
     * @see #isScientificNotation
     * @see #getMinimumExponentDigits
     * @see #isExponentSignAlwaysShown
     * @see #setExponentSignAlwaysShown
     * @stable ICU 2.0
     */
    public void setMinimumExponentDigits(byte minExpDig) {
        if (minExpDig < 1) {
            throw new IllegalArgumentException("Exponent digits must be >= 1");
        }
        minExponentDigits = minExpDig;
    }

    /**
     * {@icu} Returns whether the exponent sign is always shown.
     *
     * @return true if the exponent is always prefixed with either the localized minus
     * sign or the localized plus sign, false if only negative exponents are prefixed with
     * the localized minus sign.
     * @see #setScientificNotation
     * @see #isScientificNotation
     * @see #setMinimumExponentDigits
     * @see #getMinimumExponentDigits
     * @see #setExponentSignAlwaysShown
     * @stable ICU 2.0
     */
    public boolean isExponentSignAlwaysShown() {
        return exponentSignAlwaysShown;
    }

    /**
     * {@icu} Sets whether the exponent sign is always shown. This has no effect unless
     * scientific notation is in use.
     *
     * @param expSignAlways true if the exponent is always prefixed with either the
     * localized minus sign or the localized plus sign, false if only negative exponents
     * are prefixed with the localized minus sign.
     * @see #setScientificNotation
     * @see #isScientificNotation
     * @see #setMinimumExponentDigits
     * @see #getMinimumExponentDigits
     * @see #isExponentSignAlwaysShown
     * @stable ICU 2.0
     */
    public void setExponentSignAlwaysShown(boolean expSignAlways) {
        exponentSignAlwaysShown = expSignAlways;
    }

    /**
     * Returns the grouping size. Grouping size is the number of digits between grouping
     * separators in the integer portion of a number. For example, in the number
     * "123,456.78", the grouping size is 3.
     *
     * @see #setGroupingSize
     * @see NumberFormat#isGroupingUsed
     * @see DecimalFormatSymbols#getGroupingSeparator
     * @stable ICU 2.0
     */
    public int getGroupingSize() {
        return groupingSize;
    }

    /**
     * Sets the grouping size. Grouping size is the number of digits between grouping
     * separators in the integer portion of a number. For example, in the number
     * "123,456.78", the grouping size is 3.
     *
     * @see #getGroupingSize
     * @see NumberFormat#setGroupingUsed
     * @see DecimalFormatSymbols#setGroupingSeparator
     * @stable ICU 2.0
     */
    public void setGroupingSize(int newValue) {
        groupingSize = (byte) newValue;
    }

    /**
     * {@icu} Returns the secondary grouping size. In some locales one grouping interval
     * is used for the least significant integer digits (the primary grouping size), and
     * another is used for all others (the secondary grouping size). A formatter
     * supporting a secondary grouping size will return a positive integer unequal to the
     * primary grouping size returned by <code>getGroupingSize()</code>. For example, if
     * the primary grouping size is 4, and the secondary grouping size is 2, then the
     * number 123456789 formats as "1,23,45,6789", and the pattern appears as "#,##,###0".
     *
     * @return the secondary grouping size, or a value less than one if there is none
     * @see #setSecondaryGroupingSize
     * @see NumberFormat#isGroupingUsed
     * @see DecimalFormatSymbols#getGroupingSeparator
     * @stable ICU 2.0
     */
    public int getSecondaryGroupingSize() {
        return groupingSize2;
    }

    /**
     * {@icu} Sets the secondary grouping size. If set to a value less than 1, then
     * secondary grouping is turned off, and the primary grouping size is used for all
     * intervals, not just the least significant.
     *
     * @see #getSecondaryGroupingSize
     * @see NumberFormat#setGroupingUsed
     * @see DecimalFormatSymbols#setGroupingSeparator
     * @stable ICU 2.0
     */
    public void setSecondaryGroupingSize(int newValue) {
        groupingSize2 = (byte) newValue;
    }

    /**
     * {@icu} Returns the MathContext used by this format.
     *
     * @return desired MathContext
     * @see #getMathContext
     * @stable ICU 4.2
     */
    public MathContext getMathContextICU() {
        return mathContext;
    }

    /**
     * {@icu} Returns the MathContext used by this format.
     *
     * @return desired MathContext
     * @see #getMathContext
     * @stable ICU 4.2
     */
    public java.math.MathContext getMathContext() {
        try {
            // don't allow multiple references
            return mathContext == null ? null : new java.math.MathContext(mathContext.getDigits(),
                    java.math.RoundingMode.valueOf(mathContext.getRoundingMode()));
        } catch (Exception foo) {
            return null; // should never happen
        }
    }

    /**
     * {@icu} Sets the MathContext used by this format.
     *
     * @param newValue desired MathContext
     * @see #getMathContext
     * @stable ICU 4.2
     */
    public void setMathContextICU(MathContext newValue) {
        mathContext = newValue;
    }

    /**
     * {@icu} Sets the MathContext used by this format.
     *
     * @param newValue desired MathContext
     * @see #getMathContext
     * @stable ICU 4.2
     */
    public void setMathContext(java.math.MathContext newValue) {
        mathContext = new MathContext(newValue.getPrecision(), MathContext.SCIENTIFIC, false,
                                      (newValue.getRoundingMode()).ordinal());
    }

    /**
     * Returns the behavior of the decimal separator with integers. (The decimal
     * separator will always appear with decimals.)  <p> Example: Decimal ON: 12345 ->
     * 12345.; OFF: 12345 -> 12345
     *
     * @stable ICU 2.0
     */
    public boolean isDecimalSeparatorAlwaysShown() {
        return decimalSeparatorAlwaysShown;
    }

    /**
     * Sets the behavior of the decimal separator with integers. (The decimal separator
     * will always appear with decimals.)
     *
     * <p>This only affects formatting, and only where there might be no digits after the
     * decimal point, e.g., if true, 3456.00 -> "3,456." if false, 3456.00 -> "3456" This
     * is independent of parsing. If you want parsing to stop at the decimal point, use
     * setParseIntegerOnly.
     *
     * <p>
     * Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
     *
     * @stable ICU 2.0
     */
    public void setDecimalSeparatorAlwaysShown(boolean newValue) {
        decimalSeparatorAlwaysShown = newValue;
    }

    /**
     * {@icu} Returns a copy of the CurrencyPluralInfo used by this format. It might
     * return null if the decimal format is not a plural type currency decimal
     * format. Plural type currency decimal format means either the pattern in the decimal
     * format contains 3 currency signs, or the decimal format is initialized with
     * PLURALCURRENCYSTYLE.
     *
     * @return desired CurrencyPluralInfo
     * @see CurrencyPluralInfo
     * @stable ICU 4.2
     */
    public CurrencyPluralInfo getCurrencyPluralInfo() {
        try {
            // don't allow multiple references
            return currencyPluralInfo == null ? null :
                (CurrencyPluralInfo) currencyPluralInfo.clone();
        } catch (Exception foo) {
            return null; // should never happen
        }
    }

    /**
     * {@icu} Sets the CurrencyPluralInfo used by this format. The format uses a copy of
     * the provided information.
     *
     * @param newInfo desired CurrencyPluralInfo
     * @see CurrencyPluralInfo
     * @stable ICU 4.2
     */
    public void setCurrencyPluralInfo(CurrencyPluralInfo newInfo) {
        currencyPluralInfo = (CurrencyPluralInfo) newInfo.clone();
        isReadyForParsing = false;
    }

    /**
     * Overrides clone.
     * @stable ICU 2.0
     */
    @Override
    public Object clone() {
        try {
            DecimalFormat other = (DecimalFormat) super.clone();
            other.symbols = (DecimalFormatSymbols) symbols.clone();
            other.digitList = new DigitList(); // fix for JB#5358
            if (currencyPluralInfo != null) {
                other.currencyPluralInfo = (CurrencyPluralInfo) currencyPluralInfo.clone();
            }
            other.attributes = new ArrayList<FieldPosition>(); // #9240

            // TODO: We need to figure out whether we share a single copy of DigitList by
            // multiple cloned copies.  format/subformat are designed to use a single
            // instance, but parse/subparse implementation is not.
            return other;
        } catch (Exception e) {
            throw new IllegalStateException();
        }
    }

    /**
     * Overrides equals.
     * @stable ICU 2.0
     */
    @Override
    public boolean equals(Object obj) {
        if (obj == null)
            return false;
        if (!super.equals(obj))
            return false; // super does class check

        DecimalFormat other = (DecimalFormat) obj;
        // Add the comparison of the four new added fields ,they are posPrefixPattern,
        // posSuffixPattern, negPrefixPattern, negSuffixPattern. [Richard/GCL]
        // following are added to accomodate changes for currency plural format.
        return currencySignCount == other.currencySignCount
                && (style != NumberFormat.PLURALCURRENCYSTYLE ||
                    equals(posPrefixPattern, other.posPrefixPattern)
                && equals(posSuffixPattern, other.posSuffixPattern)
                && equals(negPrefixPattern, other.negPrefixPattern)
                && equals(negSuffixPattern, other.negSuffixPattern))
                && multiplier == other.multiplier
                && groupingSize == other.groupingSize
                && groupingSize2 == other.groupingSize2
                && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
                && useExponentialNotation == other.useExponentialNotation
                && (!useExponentialNotation || minExponentDigits == other.minExponentDigits)
                && useSignificantDigits == other.useSignificantDigits
                && (!useSignificantDigits || minSignificantDigits == other.minSignificantDigits
                        && maxSignificantDigits == other.maxSignificantDigits)
                && symbols.equals(other.symbols)
                && Utility.objectEquals(currencyPluralInfo, other.currencyPluralInfo);
    }

    // method to unquote the strings and compare
    private boolean equals(String pat1, String pat2) {
        if (pat1 == null || pat2 == null) {
            return (pat1 == null && pat2 == null);
        }
        // fast path
        if (pat1.equals(pat2)) {
            return true;
        }
        return unquote(pat1).equals(unquote(pat2));
    }

    private String unquote(String pat) {
        StringBuilder buf = new StringBuilder(pat.length());
        int i = 0;
        while (i < pat.length()) {
            char ch = pat.charAt(i++);
            if (ch != QUOTE) {
                buf.append(ch);
            }
        }
        return buf.toString();
    }

    // protected void handleToString(StringBuffer buf) {
    // buf.append("\nposPrefixPattern: '" + posPrefixPattern + "'\n");
    // buf.append("positivePrefix: '" + positivePrefix + "'\n");
    // buf.append("posSuffixPattern: '" + posSuffixPattern + "'\n");
    // buf.append("positiveSuffix: '" + positiveSuffix + "'\n");
    // buf.append("negPrefixPattern: '" +
    //     com.ibm.icu.impl.Utility.format1ForSource(negPrefixPattern) + "'\n");
    // buf.append("negativePrefix: '" +
    //     com.ibm.icu.impl.Utility.format1ForSource(negativePrefix) + "'\n");
    // buf.append("negSuffixPattern: '" + negSuffixPattern + "'\n");
    // buf.append("negativeSuffix: '" + negativeSuffix + "'\n");
    // buf.append("multiplier: '" + multiplier + "'\n");
    // buf.append("groupingSize: '" + groupingSize + "'\n");
    // buf.append("groupingSize2: '" + groupingSize2 + "'\n");
    // buf.append("decimalSeparatorAlwaysShown: '" + decimalSeparatorAlwaysShown + "'\n");
    // buf.append("useExponentialNotation: '" + useExponentialNotation + "'\n");
    // buf.append("minExponentDigits: '" + minExponentDigits + "'\n");
    // buf.append("useSignificantDigits: '" + useSignificantDigits + "'\n");
    // buf.append("minSignificantDigits: '" + minSignificantDigits + "'\n");
    // buf.append("maxSignificantDigits: '" + maxSignificantDigits + "'\n");
    // buf.append("symbols: '" + symbols + "'");
    // }

    /**
     * Overrides hashCode.
     * @stable ICU 2.0
     */
    @Override
    public int hashCode() {
        return super.hashCode() * 37 + positivePrefix.hashCode();
        // just enough fields for a reasonable distribution
    }

    /**
     * Synthesizes a pattern string that represents the current state of this Format
     * object.
     *
     * @see #applyPattern
     * @stable ICU 2.0
     */
    public String toPattern() {
        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
            // the prefix or suffix pattern might not be defined yet, so they can not be
            // synthesized, instead, get them directly.  but it might not be the actual
            // pattern used in formatting.  the actual pattern used in formatting depends
            // on the formatted number's plural count.
            return formatPattern;
        }
        return toPattern(false);
    }

    /**
     * Synthesizes a localized pattern string that represents the current state of this
     * Format object.
     *
     * @see #applyPattern
     * @stable ICU 2.0
     */
    public String toLocalizedPattern() {
        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
            return formatPattern;
        }
        return toPattern(true);
    }

    /**
     * Expands the affix pattern strings into the expanded affix strings. If any affix
     * pattern string is null, do not expand it. This method should be called any time the
     * symbols or the affix patterns change in order to keep the expanded affix strings up
     * to date. This method also will be called before formatting if format currency
     * plural names, since the plural name is not a static one, it is based on the
     * currency plural count, the affix will be known only after the currency plural count
     * is know. In which case, the parameter 'pluralCount' will be a non-null currency
     * plural count. In all other cases, the 'pluralCount' is null, which means it is not
     * needed.
     */
    // Bug 4212072 [Richard/GCL]
    private void expandAffixes(String pluralCount) {
        // expandAffix() will set currencyChoice to a non-null value if
        // appropriate AND if it is null.
        currencyChoice = null;

        // Reuse one StringBuffer for better performance
        StringBuffer buffer = new StringBuffer();
        if (posPrefixPattern != null) {
            expandAffix(posPrefixPattern, pluralCount, buffer, false);
            positivePrefix = buffer.toString();
        }
        if (posSuffixPattern != null) {
            expandAffix(posSuffixPattern, pluralCount, buffer, false);
            positiveSuffix = buffer.toString();
        }
        if (negPrefixPattern != null) {
            expandAffix(negPrefixPattern, pluralCount, buffer, false);
            negativePrefix = buffer.toString();
        }
        if (negSuffixPattern != null) {
            expandAffix(negSuffixPattern, pluralCount, buffer, false);
            negativeSuffix = buffer.toString();
        }
    }

    /**
     * Expands an affix pattern into an affix string. All characters in the pattern are
     * literal unless bracketed by QUOTEs. The following characters outside QUOTE are
     * recognized: PATTERN_PERCENT, PATTERN_PER_MILLE, PATTERN_MINUS, and
     * CURRENCY_SIGN. If CURRENCY_SIGN is doubled, it is interpreted as an international
     * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as currency plural
     * long names, such as "US Dollars". Any other character outside QUOTE represents
     * itself. Quoted text must be well-formed.
     *
     * This method is used in two distinct ways. First, it is used to expand the stored
     * affix patterns into actual affixes. For this usage, doFormat must be false. Second,
     * it is used to expand the stored affix patterns given a specific number (doFormat ==
     * true), for those rare cases in which a currency format references a ChoiceFormat
     * (e.g., en_IN display name for INR). The number itself is taken from digitList.
     *
     * When used in the first way, this method has a side effect: It sets currencyChoice
     * to a ChoiceFormat object, if the currency's display name in this locale is a
     * ChoiceFormat pattern (very rare). It only does this if currencyChoice is null to
     * start with.
     *
     * @param pattern the non-null, possibly empty pattern
     * @param pluralCount the plural count. It is only used for currency plural format. In
     * which case, it is the plural count of the currency amount. For example, in en_US,
     * it is the singular "one", or the plural "other". For all other cases, it is null,
     * and is not being used.
     * @param buffer a scratch StringBuffer; its contents will be lost
     * @param doFormat if false, then the pattern will be expanded, and if a currency
     * symbol is encountered that expands to a ChoiceFormat, the currencyChoice member
     * variable will be initialized if it is null. If doFormat is true, then it is assumed
     * that the currencyChoice has been created, and it will be used to format the value
     * in digitList.
     */
    // Bug 4212072 [Richard/GCL]
    private void expandAffix(String pattern, String pluralCount, StringBuffer buffer,
                             boolean doFormat) {
        buffer.setLength(0);
        for (int i = 0; i < pattern.length();) {
            char c = pattern.charAt(i++);
            if (c == QUOTE) {
                for (;;) {
                    int j = pattern.indexOf(QUOTE, i);
                    if (j == i) {
                        buffer.append(QUOTE);
                        i = j + 1;
                        break;
                    } else if (j > i) {
                        buffer.append(pattern.substring(i, j));
                        i = j + 1;
                        if (i < pattern.length() && pattern.charAt(i) == QUOTE) {
                            buffer.append(QUOTE);
                            ++i;
                            // loop again
                        } else {
                            break;
                        }
                    } else {
                        // Unterminated quote; should be caught by apply
                        // pattern.
                        throw new RuntimeException();
                    }
                }
                continue;
            }

            switch (c) {
            case CURRENCY_SIGN:
                // As of ICU 2.2 we use the currency object, and ignore the currency
                // symbols in the DFS, unless we have a null currency object. This occurs
                // if resurrecting a pre-2.2 object or if the user sets a custom DFS.
                boolean intl = i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN;
                boolean plural = false;
                if (intl) {
                    ++i;
                    if (i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN) {
                        plural = true;
                        intl = false;
                        ++i;
                    }
                }
                String s = null;
                Currency currency = getCurrency();
                if (currency != null) {
                    // plural name is only needed when pluralCount != null, which means
                    // when formatting currency plural names.  For other cases,
                    // pluralCount == null, and plural names are not needed.
                    if (plural && pluralCount != null) {
                        boolean isChoiceFormat[] = new boolean[1];
                        s = currency.getName(symbols.getULocale(), Currency.PLURAL_LONG_NAME,
                                             pluralCount, isChoiceFormat);
                    } else if (!intl) {
                        boolean isChoiceFormat[] = new boolean[1];
                        s = currency.getName(symbols.getULocale(), Currency.SYMBOL_NAME,
                                             isChoiceFormat);
                        if (isChoiceFormat[0]) {
                            // Two modes here: If doFormat is false, we set up
                            // currencyChoice. If doFormat is true, we use the previously
                            // created currencyChoice to format the value in digitList.
                            if (!doFormat) {
                                // If the currency is handled by a ChoiceFormat, then
                                // we're not going to use the expanded
                                // patterns. Instantiate the ChoiceFormat and return.
                                if (currencyChoice == null) {
                                    currencyChoice = new ChoiceFormat(s);
                                }
                                // We could almost return null or "" here, since the
                                // expanded affixes are almost not used at all in this
                                // situation. However, one method -- toPattern() -- still
                                // does use the expanded affixes, in order to set up a
                                // padding pattern. We use the CURRENCY_SIGN as a
                                // placeholder.
                                s = String.valueOf(CURRENCY_SIGN);
                            } else {
                                FieldPosition pos = new FieldPosition(0); // ignored
                                currencyChoice.format(digitList.getDouble(), buffer, pos);
                                continue;
                            }
                        }
                    } else {
                        s = currency.getCurrencyCode();
                    }
                } else {
                    s = intl ? symbols.getInternationalCurrencySymbol() :
                        symbols.getCurrencySymbol();
                }
                buffer.append(s);
                continue;
            case PATTERN_PERCENT:
                c = symbols.getPercent();
                break;
            case PATTERN_PER_MILLE:
                c = symbols.getPerMill();
                break;
            case PATTERN_MINUS:
                String minusString = symbols.getMinusString();
                buffer.append(minusString);
                continue;
            }
            buffer.append(c);
        }
    }

    /**
     * Append an affix to the given StringBuffer.
     *
     * @param buf
     *            buffer to append to
     * @param isNegative
     * @param isPrefix
     */
    private int appendAffix(StringBuffer buf, boolean isNegative, boolean isPrefix,
                            boolean parseAttr) {
        if (currencyChoice != null) {
            String affixPat = null;
            if (isPrefix) {
                affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
            } else {
                affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
            }
            StringBuffer affixBuf = new StringBuffer();
            expandAffix(affixPat, null, affixBuf, true);
            buf.append(affixBuf);
            return affixBuf.length();
        }

        String affix = null;
        if (isPrefix) {
            affix = isNegative ? negativePrefix : positivePrefix;
        } else {
            affix = isNegative ? negativeSuffix : positiveSuffix;
        }
        // [Spark/CDL] Invoke formatAffix2Attribute to add attributes for affix
        if (parseAttr) {
            int offset = affix.indexOf(symbols.getCurrencySymbol());
            if (-1 == offset) {
                offset = affix.indexOf(symbols.getPercent());
                if (-1 == offset) {
                    offset = 0;
                }
            }
            formatAffix2Attribute(affix, buf.length() + offset, buf.length() + affix.length());
        }
        buf.append(affix);
        return affix.length();
    }

    /**
     * [Spark/CDL] This is a newly added method, used to add attributes for prefix and
     * suffix.
     */
    private void formatAffix2Attribute(String affix, int begin, int end) {
        // [Spark/CDL] It is the invoker's responsibility to ensure that, before the
        // invocation of this method, attributes is not null.  if( attributes == null )
        // return;
        if (affix.indexOf(symbols.getCurrencySymbol()) > -1) {
            addAttribute(Field.CURRENCY, begin, end);
        } else if (affix.indexOf(symbols.getMinusSign()) > -1) {
            addAttribute(Field.SIGN, begin, end);
        } else if (affix.indexOf(symbols.getPercent()) > -1) {
            addAttribute(Field.PERCENT, begin, end);
        } else if (affix.indexOf(symbols.getPerMill()) > -1) {
            addAttribute(Field.PERMILLE, begin, end);
        }
    }

    /**
     * [Spark/CDL] Use this method to add attribute.
     */
    private void addAttribute(Field field, int begin, int end) {
        FieldPosition pos = new FieldPosition(field);
        pos.setBeginIndex(begin);
        pos.setEndIndex(end);
        attributes.add(pos);
    }

    /**
     * Formats the object to an attributed string, and return the corresponding iterator.
     *
     * @stable ICU 3.6
     */
    @Override
    public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
      return formatToCharacterIterator(obj, NULL_UNIT);
    }

    AttributedCharacterIterator formatToCharacterIterator(Object obj, Unit unit) {
        if (!(obj instanceof Number))
            throw new IllegalArgumentException();
        Number number = (Number) obj;
        StringBuffer text = new StringBuffer();
        unit.writePrefix(text);
        attributes.clear();
        if (obj instanceof BigInteger) {
            format((BigInteger) number, text, new FieldPosition(0), true);
        } else if (obj instanceof java.math.BigDecimal) {
            format((java.math.BigDecimal) number, text, new FieldPosition(0)
                          , true);
        } else if (obj instanceof Double) {
            format(number.doubleValue(), text, new FieldPosition(0), true);
        } else if (obj instanceof Integer || obj instanceof Long) {
            format(number.longValue(), text, new FieldPosition(0), true);
        } else {
            throw new IllegalArgumentException();
        }
        unit.writeSuffix(text);
        AttributedString as = new AttributedString(text.toString());

        // add NumberFormat field attributes to the AttributedString
        for (int i = 0; i < attributes.size(); i++) {
            FieldPosition pos = attributes.get(i);
            Format.Field attribute = pos.getFieldAttribute();
            as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos.getEndIndex());
        }

        // return the CharacterIterator from AttributedString
        return as.getIterator();
    }

    /**
     * Appends an affix pattern to the given StringBuffer. Localize unquoted specials.
     */
    private void appendAffixPattern(StringBuffer buffer, boolean isNegative, boolean isPrefix,
                                    boolean localized) {
        String affixPat = null;
        if (isPrefix) {
            affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
        } else {
            affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
        }

        // When there is a null affix pattern, we use the affix itself.
        if (affixPat == null) {
            String affix = null;
            if (isPrefix) {
                affix = isNegative ? negativePrefix : positivePrefix;
            } else {
                affix = isNegative ? negativeSuffix : positiveSuffix;
            }
            // Do this crudely for now: Wrap everything in quotes.
            buffer.append(QUOTE);
            for (int i = 0; i < affix.length(); ++i) {
                char ch = affix.charAt(i);
                if (ch == QUOTE) {
                    buffer.append(ch);
                }
                buffer.append(ch);
            }
            buffer.append(QUOTE);
            return;
        }

        if (!localized) {
            buffer.append(affixPat);
        } else {
            int i, j;
            for (i = 0; i < affixPat.length(); ++i) {
                char ch = affixPat.charAt(i);
                switch (ch) {
                case QUOTE:
                    j = affixPat.indexOf(QUOTE, i + 1);
                    if (j < 0) {
                        throw new IllegalArgumentException("Malformed affix pattern: " + affixPat);
                    }
                    buffer.append(affixPat.substring(i, j + 1));
                    i = j;
                    continue;
                case PATTERN_PER_MILLE:
                    ch = symbols.getPerMill();
                    break;
                case PATTERN_PERCENT:
                    ch = symbols.getPercent();
                    break;
                case PATTERN_MINUS:
                    ch = symbols.getMinusSign();
                    break;
                }
                // check if char is same as any other symbol
                if (ch == symbols.getDecimalSeparator() || ch == symbols.getGroupingSeparator()) {
                    buffer.append(QUOTE);
                    buffer.append(ch);
                    buffer.append(QUOTE);
                } else {
                    buffer.append(ch);
                }
            }
        }
    }

    /**
     * Does the real work of generating a pattern.
     */
    private String toPattern(boolean localized) {
        StringBuffer result = new StringBuffer();
        char zero = localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT;
        char digit = localized ? symbols.getDigit() : PATTERN_DIGIT;
        char sigDigit = 0;
        boolean useSigDig = areSignificantDigitsUsed();
        if (useSigDig) {
            sigDigit = localized ? symbols.getSignificantDigit() : PATTERN_SIGNIFICANT_DIGIT;
        }
        char group = localized ? symbols.getGroupingSeparator() : PATTERN_GROUPING_SEPARATOR;
        int i;
        int roundingDecimalPos = 0; // Pos of decimal in roundingDigits
        String roundingDigits = null;
        int padPos = (formatWidth > 0) ? padPosition : -1;
        String padSpec = (formatWidth > 0)
            ? new StringBuffer(2).append(localized
                                         ? symbols.getPadEscape()
                                         : PATTERN_PAD_ESCAPE).append(pad).toString()
            : null;
        if (roundingIncrementICU != null) {
            i = roundingIncrementICU.scale();
            roundingDigits = roundingIncrementICU.movePointRight(i).toString();
            roundingDecimalPos = roundingDigits.length() - i;
        }
        for (int part = 0; part < 2; ++part) {
            // variable not used int partStart = result.length();
            if (padPos == PAD_BEFORE_PREFIX) {
                result.append(padSpec);
            }

            // Use original symbols read from resources in pattern eg. use "\u00A4"
            // instead of "$" in Locale.US [Richard/GCL]
            appendAffixPattern(result, part != 0, true, localized);
            if (padPos == PAD_AFTER_PREFIX) {
                result.append(padSpec);
            }
            int sub0Start = result.length();
            int g = isGroupingUsed() ? Math.max(0, groupingSize) : 0;
            if (g > 0 && groupingSize2 > 0 && groupingSize2 != groupingSize) {
                g += groupingSize2;
            }
            int maxDig = 0, minDig = 0, maxSigDig = 0;
            if (useSigDig) {
                minDig = getMinimumSignificantDigits();
                maxDig = maxSigDig = getMaximumSignificantDigits();
            } else {
                minDig = getMinimumIntegerDigits();
                maxDig = getMaximumIntegerDigits();
            }
            if (useExponentialNotation) {
                if (maxDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
                    maxDig = 1;
                }
            } else if (useSigDig) {
                maxDig = Math.max(maxDig, g + 1);
            } else {
                maxDig = Math.max(Math.max(g, getMinimumIntegerDigits()), roundingDecimalPos) + 1;
            }
            for (i = maxDig; i > 0; --i) {
                if (!useExponentialNotation && i < maxDig && isGroupingPosition(i)) {
                    result.append(group);
                }
                if (useSigDig) {
                    // #@,@### (maxSigDig == 5, minSigDig == 2) 65 4321 (1-based pos,
                    // count from the right) Use # if pos > maxSigDig or 1 <= pos <=
                    // (maxSigDig - minSigDig) Use @ if (maxSigDig - minSigDig) < pos <=
                    // maxSigDig
                    result.append((maxSigDig >= i && i > (maxSigDig - minDig)) ? sigDigit : digit);
                } else {
                    if (roundingDigits != null) {
                        int pos = roundingDecimalPos - i;
                        if (pos >= 0 && pos < roundingDigits.length()) {
                            result.append((char) (roundingDigits.charAt(pos) - '0' + zero));
                            continue;
                        }
                    }
                    result.append(i <= minDig ? zero : digit);
                }
            }
            if (!useSigDig) {
                if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) {
                    result.append(localized ? symbols.getDecimalSeparator() :
                                  PATTERN_DECIMAL_SEPARATOR);
                }
                int pos = roundingDecimalPos;
                for (i = 0; i < getMaximumFractionDigits(); ++i) {
                    if (roundingDigits != null && pos < roundingDigits.length()) {
                        result.append(pos < 0 ? zero :
                                      (char) (roundingDigits.charAt(pos) - '0' + zero));
                        ++pos;
                        continue;
                    }
                    result.append(i < getMinimumFractionDigits() ? zero : digit);
                }
            }
            if (useExponentialNotation) {
                if (localized) {
                    result.append(symbols.getExponentSeparator());
                } else {
                    result.append(PATTERN_EXPONENT);
                }
                if (exponentSignAlwaysShown) {
                    result.append(localized ? symbols.getPlusSign() : PATTERN_PLUS_SIGN);
                }
                for (i = 0; i < minExponentDigits; ++i) {
                    result.append(zero);
                }
            }
            if (padSpec != null && !useExponentialNotation) {
                int add = formatWidth
                        - result.length()
                        + sub0Start
                        - ((part == 0)
                           ? positivePrefix.length() + positiveSuffix.length()
                           : negativePrefix.length() + negativeSuffix.length());
                while (add > 0) {
                    result.insert(sub0Start, digit);
                    ++maxDig;
                    --add;
                    // Only add a grouping separator if we have at least 2 additional
                    // characters to be added, so we don't end up with ",###".
                    if (add > 1 && isGroupingPosition(maxDig)) {
                        result.insert(sub0Start, group);
                        --add;
                    }
                }
            }
            if (padPos == PAD_BEFORE_SUFFIX) {
                result.append(padSpec);
            }
            // Use original symbols read from resources in pattern eg. use "\u00A4"
            // instead of "$" in Locale.US [Richard/GCL]
            appendAffixPattern(result, part != 0, false, localized);
            if (padPos == PAD_AFTER_SUFFIX) {
                result.append(padSpec);
            }
            if (part == 0) {
                if (negativeSuffix.equals(positiveSuffix) &&
                    negativePrefix.equals(PATTERN_MINUS + positivePrefix)) {
                    break;
                } else {
                    result.append(localized ? symbols.getPatternSeparator() : PATTERN_SEPARATOR);
                }
            }
        }
        return result.toString();
    }

    /**
     * Applies the given pattern to this Format object. A pattern is a short-hand
     * specification for the various formatting properties. These properties can also be
     * changed individually through the various setter methods.
     *
     * <p>There is no limit to integer digits are set by this routine, since that is the
     * typical end-user desire; use setMaximumInteger if you want to set a real value. For
     * negative numbers, use a second pattern, separated by a semicolon
     *
     * <p>Example "#,#00.0#" -> 1,234.56
     *
     * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2
     * fraction digits.
     *
     * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parentheses.
     *
     * <p>In negative patterns, the minimum and maximum counts are ignored; these are
     * presumed to be set in the positive pattern.
     *
     * @stable ICU 2.0
     */
    public void applyPattern(String pattern) {
        applyPattern(pattern, false);
    }

    /**
     * Applies the given pattern to this Format object. The pattern is assumed to be in a
     * localized notation. A pattern is a short-hand specification for the various
     * formatting properties. These properties can also be changed individually through
     * the various setter methods.
     *
     * <p>There is no limit to integer digits are set by this routine, since that is the
     * typical end-user desire; use setMaximumInteger if you want to set a real value. For
     * negative numbers, use a second pattern, separated by a semicolon
     *
     * <p>Example "#,#00.0#" -> 1,234.56
     *
     * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2
     * fraction digits.
     *
     * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses.
     *
     * <p>In negative patterns, the minimum and maximum counts are ignored; these are
     * presumed to be set in the positive pattern.
     *
     * @stable ICU 2.0
     */
    public void applyLocalizedPattern(String pattern) {
        applyPattern(pattern, true);
    }

    /**
     * Does the real work of applying a pattern.
     */
    private void applyPattern(String pattern, boolean localized) {
        applyPatternWithoutExpandAffix(pattern, localized);
        expandAffixAdjustWidth(null);
    }

    private void expandAffixAdjustWidth(String pluralCount) {
        // Bug 4212072 Update the affix strings according to symbols in order to keep the
        // affix strings up to date.  [Richard/GCL]
        expandAffixes(pluralCount);

        // Now that we have the actual prefix and suffix, fix up formatWidth
        if (formatWidth > 0) {
            formatWidth += positivePrefix.length() + positiveSuffix.length();
        }
    }

    private void applyPatternWithoutExpandAffix(String pattern, boolean localized) {
        char zeroDigit = PATTERN_ZERO_DIGIT; // '0'
        char sigDigit = PATTERN_SIGNIFICANT_DIGIT; // '@'
        char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
        char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;
        char percent = PATTERN_PERCENT;
        char perMill = PATTERN_PER_MILLE;
        char digit = PATTERN_DIGIT; // '#'
        char separator = PATTERN_SEPARATOR;
        String exponent = String.valueOf(PATTERN_EXPONENT);
        char plus = PATTERN_PLUS_SIGN;
        char padEscape = PATTERN_PAD_ESCAPE;
        char minus = PATTERN_MINUS; // Bug 4212072 [Richard/GCL]
        if (localized) {
            zeroDigit = symbols.getZeroDigit();
            sigDigit = symbols.getSignificantDigit();
            groupingSeparator = symbols.getGroupingSeparator();
            decimalSeparator = symbols.getDecimalSeparator();
            percent = symbols.getPercent();
            perMill = symbols.getPerMill();
            digit = symbols.getDigit();
            separator = symbols.getPatternSeparator();
            exponent = symbols.getExponentSeparator();
            plus = symbols.getPlusSign();
            padEscape = symbols.getPadEscape();
            minus = symbols.getMinusSign(); // Bug 4212072 [Richard/GCL]
        }
        char nineDigit = (char) (zeroDigit + 9);

        boolean gotNegative = false;

        int pos = 0;
        // Part 0 is the positive pattern. Part 1, if present, is the negative
        // pattern.
        for (int part = 0; part < 2 && pos < pattern.length(); ++part) {
            // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix, 2=suffix,
            // 3=prefix in quote, 4=suffix in quote. Subpart 0 is between the prefix and
            // suffix, and consists of pattern characters. In the prefix and suffix,
            // percent, permille, and currency symbols are recognized and translated.
            int subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0;

            // It's important that we don't change any fields of this object
            // prematurely. We set the following variables for the multiplier, grouping,
            // etc., and then only change the actual object fields if everything parses
            // correctly. This also lets us register the data from part 0 and ignore the
            // part 1, except for the prefix and suffix.
            StringBuilder prefix = new StringBuilder();
            StringBuilder suffix = new StringBuilder();
            int decimalPos = -1;
            int multpl = 1;
            int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0;
            byte groupingCount = -1;
            byte groupingCount2 = -1;
            int padPos = -1;
            char padChar = 0;
            int incrementPos = -1;
            long incrementVal = 0;
            byte expDigits = -1;
            boolean expSignAlways = false;
            int currencySignCnt = 0;

            // The affix is either the prefix or the suffix.
            StringBuilder affix = prefix;

            int start = pos;

            PARTLOOP: for (; pos < pattern.length(); ++pos) {
                char ch = pattern.charAt(pos);
                switch (subpart) {
                case 0: // Pattern proper subpart (between prefix & suffix)
                    // Process the digits, decimal, and grouping characters. We record
                    // five pieces of information. We expect the digits to occur in the
                    // pattern ####00.00####, and we record the number of left digits,
                    // zero (central) digits, and right digits. The position of the last
                    // grouping character is recorded (should be somewhere within the
                    // first two blocks of characters), as is the position of the decimal
                    // point, if any (should be in the zero digits). If there is no
                    // decimal point, then there should be no right digits.
                    if (ch == digit) {
                        if (zeroDigitCount > 0 || sigDigitCount > 0) {
                            ++digitRightCount;
                        } else {
                            ++digitLeftCount;
                        }
                        if (groupingCount >= 0 && decimalPos < 0) {
                            ++groupingCount;
                        }
                    } else if ((ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) {
                        if (digitRightCount > 0) {
                            patternError("Unexpected '" + ch + '\'', pattern);
                        }
                        if (ch == sigDigit) {
                            ++sigDigitCount;
                        } else {
                            ++zeroDigitCount;
                            if (ch != zeroDigit) {
                                int p = digitLeftCount + zeroDigitCount + digitRightCount;
                                if (incrementPos >= 0) {
                                    while (incrementPos < p) {
                                        incrementVal *= 10;
                                        ++incrementPos;
                                    }
                                } else {
                                    incrementPos = p;
                                }
                                incrementVal += ch - zeroDigit;
                            }
                        }
                        if (groupingCount >= 0 && decimalPos < 0) {
                            ++groupingCount;
                        }
                    } else if (ch == groupingSeparator) {
                        // Bug 4212072 process the Localized pattern like
                        // "'Fr. '#'##0.05;'Fr.-'#'##0.05" (Locale="CH", groupingSeparator
                        // == QUOTE) [Richard/GCL]
                        if (ch == QUOTE && (pos + 1) < pattern.length()) {
                            char after = pattern.charAt(pos + 1);
                            if (!(after == digit || (after >= zeroDigit && after <= nineDigit))) {
                                // A quote outside quotes indicates either the opening
                                // quote or two quotes, which is a quote literal. That is,
                                // we have the first quote in 'do' or o''clock.
                                if (after == QUOTE) {
                                    ++pos;
                                    // Fall through to append(ch)
                                } else {
                                    if (groupingCount < 0) {
                                        subpart = 3; // quoted prefix subpart
                                    } else {
                                        // Transition to suffix subpart
                                        subpart = 2; // suffix subpart
                                        affix = suffix;
                                        sub0Limit = pos--;
                                    }
                                    continue;
                                }
                            }
                        }

                        if (decimalPos >= 0) {
                            patternError("Grouping separator after decimal", pattern);
                        }
                        groupingCount2 = groupingCount;
                        groupingCount = 0;
                    } else if (ch == decimalSeparator) {
                        if (decimalPos >= 0) {
                            patternError("Multiple decimal separators", pattern);
                        }
                        // Intentionally incorporate the digitRightCount, even though it
                        // is illegal for this to be > 0 at this point. We check pattern
                        // syntax below.
                        decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
                    } else {
                        if (pattern.regionMatches(pos, exponent, 0, exponent.length())) {
                            if (expDigits >= 0) {
                                patternError("Multiple exponential symbols", pattern);
                            }
                            if (groupingCount >= 0) {
                                patternError("Grouping separator in exponential", pattern);
                            }
                            pos += exponent.length();
                            // Check for positive prefix
                            if (pos < pattern.length() && pattern.charAt(pos) == plus) {
                                expSignAlways = true;
                                ++pos;
                            }
                            // Use lookahead to parse out the exponential part of the
                            // pattern, then jump into suffix subpart.
                            expDigits = 0;
                            while (pos < pattern.length() && pattern.charAt(pos) == zeroDigit) {
                                ++expDigits;
                                ++pos;
                            }

                            // 1. Require at least one mantissa pattern digit
                            // 2. Disallow "#+ @" in mantissa
                            // 3. Require at least one exponent pattern digit
                            if (((digitLeftCount + zeroDigitCount) < 1 &&
                                 (sigDigitCount + digitRightCount) < 1)
                                || (sigDigitCount > 0 && digitLeftCount > 0) || expDigits < 1) {
                                patternError("Malformed exponential", pattern);
                            }
                        }
                        // Transition to suffix subpart
                        subpart = 2; // suffix subpart
                        affix = suffix;
                        sub0Limit = pos--; // backup: for() will increment
                        continue;
                    }
                    break;
                case 1: // Prefix subpart
                case 2: // Suffix subpart
                    // Process the prefix / suffix characters Process unquoted characters
                    // seen in prefix or suffix subpart.

                    // Several syntax characters implicitly begins the next subpart if we
                    // are in the prefix; otherwise they are illegal if unquoted.
                    if (ch == digit || ch == groupingSeparator || ch == decimalSeparator
                            || (ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) {
                        // Any of these characters implicitly begins the
                        // next subpart if we are in the prefix
                        if (subpart == 1) { // prefix subpart
                            subpart = 0; // pattern proper subpart
                            sub0Start = pos--; // Reprocess this character
                            continue;
                        } else if (ch == QUOTE) {
                            // Bug 4212072 process the Localized pattern like
                            // "'Fr. '#'##0.05;'Fr.-'#'##0.05" (Locale="CH",
                            // groupingSeparator == QUOTE) [Richard/GCL]

                            // A quote outside quotes indicates either the opening quote
                            // or two quotes, which is a quote literal. That is, we have
                            // the first quote in 'do' or o''clock.
                            if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
                                ++pos;
                                affix.append(ch);
                            } else {
                                subpart += 2; // open quote
                            }
                            continue;
                        }
                        patternError("Unquoted special character '" + ch + '\'', pattern);
                    } else if (ch == CURRENCY_SIGN) {
                        // Use lookahead to determine if the currency sign is
                        // doubled or not.
                        boolean doubled = (pos + 1) < pattern.length() &&
                            pattern.charAt(pos + 1) == CURRENCY_SIGN;

                        // Bug 4212072 To meet the need of expandAffix(String,
                        // StirngBuffer) [Richard/GCL]
                        if (doubled) {
                            ++pos; // Skip over the doubled character
                            affix.append(ch); // append two: one here, one below
                            if ((pos + 1) < pattern.length() &&
                                pattern.charAt(pos + 1) == CURRENCY_SIGN) {
                                ++pos; // Skip over the tripled character
                                affix.append(ch); // append again
                                currencySignCnt = CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT;
                            } else {
                                currencySignCnt = CURRENCY_SIGN_COUNT_IN_ISO_FORMAT;
                            }
                        } else {
                            currencySignCnt = CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT;
                        }
                        // Fall through to append(ch)
                    } else if (ch == QUOTE) {
                        // A quote outside quotes indicates either the opening quote or
                        // two quotes, which is a quote literal. That is, we have the
                        // first quote in 'do' or o''clock.
                        if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
                            ++pos;
                            affix.append(ch); // append two: one here, one below
                        } else {
                            subpart += 2; // open quote
                        }
                        // Fall through to append(ch)
                    } else if (ch == separator) {
                        // Don't allow separators in the prefix, and don't allow
                        // separators in the second pattern (part == 1).
                        if (subpart == 1 || part == 1) {
                            patternError("Unquoted special character '" + ch + '\'', pattern);
                        }
                        sub2Limit = pos++;
                        break PARTLOOP; // Go to next part
                    } else if (ch == percent || ch == perMill) {
                        // Next handle characters which are appended directly.
                        if (multpl != 1) {
                            patternError("Too many percent/permille characters", pattern);
                        }
                        multpl = (ch == percent) ? 100 : 1000;
                        // Convert to non-localized pattern
                        ch = (ch == percent) ? PATTERN_PERCENT : PATTERN_PER_MILLE;
                        // Fall through to append(ch)
                    } else if (ch == minus) {
                        // Convert to non-localized pattern
                        ch = PATTERN_MINUS;
                        // Fall through to append(ch)
                    } else if (ch == padEscape) {
                        if (padPos >= 0) {
                            patternError("Multiple pad specifiers", pattern);
                        }
                        if ((pos + 1) == pattern.length()) {
                            patternError("Invalid pad specifier", pattern);
                        }
                        padPos = pos++; // Advance past pad char
                        padChar = pattern.charAt(pos);
                        continue;
                    }
                    affix.append(ch);
                    break;
                case 3: // Prefix subpart, in quote
                case 4: // Suffix subpart, in quote
                    // A quote within quotes indicates either the closing quote or two
                    // quotes, which is a quote literal. That is, we have the second quote
                    // in 'do' or 'don''t'.
                    if (ch == QUOTE) {
                        if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
                            ++pos;
                            affix.append(ch);
                        } else {
                            subpart -= 2; // close quote
                        }
                        // Fall through to append(ch)
                    }
                    // NOTE: In ICU 2.2 there was code here to parse quoted percent and
                    // permille characters _within quotes_ and give them special
                    // meaning. This is incorrect, since quoted characters are literals
                    // without special meaning.
                    affix.append(ch);
                    break;
                }
            }

            if (subpart == 3 || subpart == 4) {
                patternError("Unterminated quote", pattern);
            }

            if (sub0Limit == 0) {
                sub0Limit = pattern.length();
            }

            if (sub2Limit == 0) {
                sub2Limit = pattern.length();
            }

            // Handle patterns with no '0' pattern character. These patterns are legal,
            // but must be recodified to make sense. "##.###" -> "#0.###". ".###" ->
            // ".0##".
            //
            // We allow patterns of the form "####" to produce a zeroDigitCount of zero
            // (got that?); although this seems like it might make it possible for
            // format() to produce empty strings, format() checks for this condition and
            // outputs a zero digit in this situation. Having a zeroDigitCount of zero
            // yields a minimum integer digits of zero, which allows proper round-trip
            // patterns. We don't want "#" to become "#0" when toPattern() is called (even
            // though that's what it really is, semantically).
            if (zeroDigitCount == 0 && sigDigitCount == 0 &&
                digitLeftCount > 0 && decimalPos >= 0) {
                // Handle "###.###" and "###." and ".###"
                int n = decimalPos;
                if (n == 0)
                    ++n; // Handle ".###"
                digitRightCount = digitLeftCount - n;
                digitLeftCount = n - 1;
                zeroDigitCount = 1;
            }

            // Do syntax checking on the digits, decimal points, and quotes.
            if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0)
                || (decimalPos >= 0
                    && (sigDigitCount > 0
                        || decimalPos < digitLeftCount
                        || decimalPos > (digitLeftCount + zeroDigitCount)))
                || groupingCount == 0
                || groupingCount2 == 0
                || (sigDigitCount > 0 && zeroDigitCount > 0)
                || subpart > 2) { // subpart > 2 == unmatched quote
                patternError("Malformed pattern", pattern);
            }

            // Make sure pad is at legal position before or after affix.
            if (padPos >= 0) {
                if (padPos == start) {
                    padPos = PAD_BEFORE_PREFIX;
                } else if (padPos + 2 == sub0Start) {
                    padPos = PAD_AFTER_PREFIX;
                } else if (padPos == sub0Limit) {
                    padPos = PAD_BEFORE_SUFFIX;
                } else if (padPos + 2 == sub2Limit) {
                    padPos = PAD_AFTER_SUFFIX;
                } else {
                    patternError("Illegal pad position", pattern);
                }
            }

            if (part == 0) {
                // Set negative affixes temporarily to match the positive
                // affixes. Fix this up later after processing both parts.

                // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer)
                // [Richard/GCL]
                posPrefixPattern = negPrefixPattern = prefix.toString();
                posSuffixPattern = negSuffixPattern = suffix.toString();

                useExponentialNotation = (expDigits >= 0);
                if (useExponentialNotation) {
                    minExponentDigits = expDigits;
                    exponentSignAlwaysShown = expSignAlways;
                }
                int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
                // The effectiveDecimalPos is the position the decimal is at or would be
                // at if there is no decimal. Note that if decimalPos<0, then
                // digitTotalCount == digitLeftCount + zeroDigitCount.
                int effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount;
                boolean useSigDig = (sigDigitCount > 0);
                setSignificantDigitsUsed(useSigDig);
                if (useSigDig) {
                    setMinimumSignificantDigits(sigDigitCount);
                    setMaximumSignificantDigits(sigDigitCount + digitRightCount);
                } else {
                    int minInt = effectiveDecimalPos - digitLeftCount;
                    setMinimumIntegerDigits(minInt);

                    // Upper limit on integer and fraction digits for a Java double
                    // [Richard/GCL]
                    setMaximumIntegerDigits(useExponentialNotation ? digitLeftCount + minInt :
                                            DOUBLE_INTEGER_DIGITS);
                    _setMaximumFractionDigits(decimalPos >= 0 ?
                                             (digitTotalCount - decimalPos) : 0);
                    setMinimumFractionDigits(decimalPos >= 0 ?
                                             (digitLeftCount + zeroDigitCount - decimalPos) : 0);
                }
                setGroupingUsed(groupingCount > 0);
                this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
                this.groupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount)
                    ? groupingCount2 : 0;
                this.multiplier = multpl;
                setDecimalSeparatorAlwaysShown(decimalPos == 0 || decimalPos == digitTotalCount);
                if (padPos >= 0) {
                    padPosition = padPos;
                    formatWidth = sub0Limit - sub0Start; // to be fixed up below
                    pad = padChar;
                } else {
                    formatWidth = 0;
                }
                if (incrementVal != 0) {
                    // BigDecimal scale cannot be negative (even though this makes perfect
                    // sense), so we need to handle this.
                    int scale = incrementPos - effectiveDecimalPos;
                    roundingIncrementICU = BigDecimal.valueOf(incrementVal, scale > 0 ? scale : 0);
                    if (scale < 0) {
                        roundingIncrementICU = roundingIncrementICU.movePointRight(-scale);
                    }
                    roundingMode = BigDecimal.ROUND_HALF_EVEN;
                } else {
                    setRoundingIncrement((BigDecimal) null);
                }

                // Update currency sign count for the new pattern
                currencySignCount = currencySignCnt;
            } else {
                // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer)
                // [Richard/GCL]
                negPrefixPattern = prefix.toString();
                negSuffixPattern = suffix.toString();
                gotNegative = true;
            }
        }


        // Bug 4140009 Process the empty pattern [Richard/GCL]
        if (pattern.length() == 0) {
            posPrefixPattern = posSuffixPattern = "";
            setMinimumIntegerDigits(0);
            setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
            setMinimumFractionDigits(0);
            _setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
        }

        // If there was no negative pattern, or if the negative pattern is identical to
        // the positive pattern, then prepend the minus sign to the positive pattern to
        // form the negative pattern.

        // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) [Richard/GCL]

        if (!gotNegative ||
            (negPrefixPattern.equals(posPrefixPattern)
             && negSuffixPattern.equals(posSuffixPattern))) {
            negSuffixPattern = posSuffixPattern;
            negPrefixPattern = PATTERN_MINUS + posPrefixPattern;
        }
        setLocale(null, null);
        // save the pattern
        formatPattern = pattern;

        // special handlings for currency instance
        if (currencySignCount != CURRENCY_SIGN_COUNT_ZERO) {
            // reset rounding increment and max/min fractional digits
            // by the currency
            Currency theCurrency = getCurrency();
            if (theCurrency != null) {
                setRoundingIncrement(theCurrency.getRoundingIncrement());
                int d = theCurrency.getDefaultFractionDigits();
                setMinimumFractionDigits(d);
                _setMaximumFractionDigits(d);
            }

            // initialize currencyPluralInfo if needed
            if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT
                && currencyPluralInfo == null) {
                currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale());
            }
        }
        resetActualRounding();
    }


    private void patternError(String msg, String pattern) {
        throw new IllegalArgumentException(msg + " in pattern \"" + pattern + '"');
    }


    // Rewrite the following 4 "set" methods Upper limit on integer and fraction digits
    // for a Java double [Richard/GCL]

    /**
     * Sets the maximum number of digits allowed in the integer portion of a number. This
     * override limits the integer digit count to 309.
     *
     * @see NumberFormat#setMaximumIntegerDigits
     * @stable ICU 2.0
     */
    @Override
    public void setMaximumIntegerDigits(int newValue) {
        super.setMaximumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
    }

    /**
     * Sets the minimum number of digits allowed in the integer portion of a number. This
     * override limits the integer digit count to 309.
     *
     * @see NumberFormat#setMinimumIntegerDigits
     * @stable ICU 2.0
     */
    @Override
    public void setMinimumIntegerDigits(int newValue) {
        super.setMinimumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
    }

    /**
     * {@icu} Returns the minimum number of significant digits that will be
     * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}
     * returns true.
     *
     * @return the fewest significant digits that will be shown
     * @stable ICU 3.0
     */
    public int getMinimumSignificantDigits() {
        return minSignificantDigits;
    }

    /**
     * {@icu} Returns the maximum number of significant digits that will be
     * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}
     * returns true.
     *
     * @return the most significant digits that will be shown
     * @stable ICU 3.0
     */
    public int getMaximumSignificantDigits() {
        return maxSignificantDigits;
    }

    /**
     * {@icu} Sets the minimum number of significant digits that will be displayed. If
     * <code>min</code> is less than one then it is set to one. If the maximum significant
     * digits count is less than <code>min</code>, then it is set to <code>min</code>. 
     * This function also enables the use of significant digits by this formatter - 
     * {@link #areSignificantDigitsUsed()} will return true.
     *
     * @param min the fewest significant digits to be shown
     * @stable ICU 3.0
     */
    public void setMinimumSignificantDigits(int min) {
        if (min < 1) {
            min = 1;
        }
        // pin max sig dig to >= min
        int max = Math.max(maxSignificantDigits, min);
        minSignificantDigits = min;
        maxSignificantDigits = max;
        setSignificantDigitsUsed(true);
    }

    /**
     * {@icu} Sets the maximum number of significant digits that will be displayed. If
     * <code>max</code> is less than one then it is set to one. If the minimum significant
     * digits count is greater than <code>max</code>, then it is set to <code>max</code>.
     * This function also enables the use of significant digits by this formatter - 
     * {@link #areSignificantDigitsUsed()} will return true.
     *
     * @param max the most significant digits to be shown
     * @stable ICU 3.0
     */
    public void setMaximumSignificantDigits(int max) {
        if (max < 1) {
            max = 1;
        }
        // pin min sig dig to 1..max
        int min = Math.min(minSignificantDigits, max);
        minSignificantDigits = min;
        maxSignificantDigits = max;
        setSignificantDigitsUsed(true);
    }

    /**
     * {@icu} Returns true if significant digits are in use or false if integer and
     * fraction digit counts are in use.
     *
     * @return true if significant digits are in use
     * @stable ICU 3.0
     */
    public boolean areSignificantDigitsUsed() {
        return useSignificantDigits;
    }

    /**
     * {@icu} Sets whether significant digits are in use, or integer and fraction digit
     * counts are in use.
     *
     * @param useSignificantDigits true to use significant digits, or false to use integer
     * and fraction digit counts
     * @stable ICU 3.0
     */
    public void setSignificantDigitsUsed(boolean useSignificantDigits) {
        this.useSignificantDigits = useSignificantDigits;
    }

    /**
     * Sets the <tt>Currency</tt> object used to display currency amounts. This takes
     * effect immediately, if this format is a currency format. If this format is not a
     * currency format, then the currency object is used if and when this object becomes a
     * currency format through the application of a new pattern.
     *
     * @param theCurrency new currency object to use. Must not be null.
     * @stable ICU 2.2
     */
    @Override
    public void setCurrency(Currency theCurrency) {
        // If we are a currency format, then modify our affixes to
        // encode the currency symbol for the given currency in our
        // locale, and adjust the decimal digits and rounding for the
        // given currency.

        super.setCurrency(theCurrency);
        if (theCurrency != null) {
            boolean[] isChoiceFormat = new boolean[1];
            String s = theCurrency.getName(symbols.getULocale(),
                                           Currency.SYMBOL_NAME, isChoiceFormat);
            symbols.setCurrency(theCurrency);
            symbols.setCurrencySymbol(s);
        }

        if (currencySignCount != CURRENCY_SIGN_COUNT_ZERO) {
            if (theCurrency != null) {
                setRoundingIncrement(theCurrency.getRoundingIncrement());
                int d = theCurrency.getDefaultFractionDigits();
                setMinimumFractionDigits(d);
                setMaximumFractionDigits(d);
            }
            if (currencySignCount != CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
                // This is not necessary for plural format type
                // because affixes will be resolved in subformat
                expandAffixes(null);
            }
        }
    }

    /**
     * Returns the currency in effect for this formatter. Subclasses should override this
     * method as needed. Unlike getCurrency(), this method should never return null.
     *
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    @Override
    protected Currency getEffectiveCurrency() {
        Currency c = getCurrency();
        if (c == null) {
            c = Currency.getInstance(symbols.getInternationalCurrencySymbol());
        }
        return c;
    }

    /**
     * Sets the maximum number of digits allowed in the fraction portion of a number. This
     * override limits the fraction digit count to 340.
     *
     * @see NumberFormat#setMaximumFractionDigits
     * @stable ICU 2.0
     */
    @Override
    public void setMaximumFractionDigits(int newValue) {
        _setMaximumFractionDigits(newValue);
        resetActualRounding();
    }

    /*
     * Internal method for DecimalFormat, setting maximum fractional digits
     * without triggering actual rounding recalculated.
     */
    private void _setMaximumFractionDigits(int newValue) {
        super.setMaximumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
    }

    /**
     * Sets the minimum number of digits allowed in the fraction portion of a number. This
     * override limits the fraction digit count to 340.
     *
     * @see NumberFormat#setMinimumFractionDigits
     * @stable ICU 2.0
     */
    @Override
    public void setMinimumFractionDigits(int newValue) {
        super.setMinimumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
    }

    /**
     * Sets whether {@link #parse(String, ParsePosition)} returns BigDecimal. The
     * default value is false.
     *
     * @param value true if {@link #parse(String, ParsePosition)}
     * returns BigDecimal.
     * @stable ICU 3.6
     */
    public void setParseBigDecimal(boolean value) {
        parseBigDecimal = value;
    }

    /**
     * Returns whether {@link #parse(String, ParsePosition)} returns BigDecimal.
     *
     * @return true if {@link #parse(String, ParsePosition)} returns BigDecimal.
     * @stable ICU 3.6
     */
    public boolean isParseBigDecimal() {
        return parseBigDecimal;
    }
    
    /**
    * Set the maximum number of exponent digits when parsing a number. 
    * If the limit is set too high, an OutOfMemoryException may be triggered.
    * The default value is 1000.
    * @param newValue the new limit
    * @draft ICU 51
    * @provisional This API might change or be removed in a future release.
    */
    public void setParseMaxDigits(int newValue) {
        if (newValue > 0) {
            PARSE_MAX_EXPONENT = newValue;
        }
    }
    
    /**
    * Get the current maximum number of exponent digits when parsing a
    * number.
    *
    * @draft ICU 51
    * @provisional This API might change or be removed in a future release.
    */
    public int getParseMaxDigits() {
        return PARSE_MAX_EXPONENT;
    }

    private void writeObject(ObjectOutputStream stream) throws IOException {
        // Ticket#6449 Format.Field instances are not serializable. When
        // formatToCharacterIterator is called, attributes (ArrayList) stores
        // FieldPosition instances with NumberFormat.Field. Because NumberFormat.Field is
        // not serializable, we need to clear the contents of the list when writeObject is
        // called. We could remove the field or make it transient, but it will break
        // serialization compatibility.
        attributes.clear();

        stream.defaultWriteObject();
    }

    /**
     * First, read the default serializable fields from the stream. Then if
     * <code>serialVersionOnStream</code> is less than 1, indicating that the stream was
     * written by JDK 1.1, initialize <code>useExponentialNotation</code> to false, since
     * it was not present in JDK 1.1. Finally, set serialVersionOnStream back to the
     * maximum allowed value so that default serialization will work properly if this
     * object is streamed out again.
     */
    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
        stream.defaultReadObject();

        // Bug 4185761 validate fields [Richard/GCL]

        // We only need to check the maximum counts because NumberFormat .readObject has
        // already ensured that the maximum is greater than the minimum count.

        // Commented for compatibility with previous version, and reserved for further use
        // if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
        // getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) { throw new
        // InvalidObjectException("Digit count out of range"); }


        // Truncate the maximumIntegerDigits to DOUBLE_INTEGER_DIGITS and
        // maximumFractionDigits to DOUBLE_FRACTION_DIGITS

        if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS) {
            setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
        }
        if (getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
            _setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
        }
        if (serialVersionOnStream < 2) {
            exponentSignAlwaysShown = false;
            setInternalRoundingIncrement(null);
            roundingMode = BigDecimal.ROUND_HALF_EVEN;
            formatWidth = 0;
            pad = ' ';
            padPosition = PAD_BEFORE_PREFIX;
            if (serialVersionOnStream < 1) {
                // Didn't have exponential fields
                useExponentialNotation = false;
            }
        }
        if (serialVersionOnStream < 3) {
            // Versions prior to 3 do not store a currency object.  Create one to match
            // the DecimalFormatSymbols object.
            setCurrencyForSymbols();
        }
        serialVersionOnStream = currentSerialVersion;
        digitList = new DigitList();

        if (roundingIncrement != null) {
            setInternalRoundingIncrement(new BigDecimal(roundingIncrement));
        }
        resetActualRounding();
    }

    private void setInternalRoundingIncrement(BigDecimal value) {
        roundingIncrementICU = value;
        roundingIncrement = value == null ? null : value.toBigDecimal();
    }

    // ----------------------------------------------------------------------
    // INSTANCE VARIABLES
    // ----------------------------------------------------------------------

    private transient DigitList digitList = new DigitList();

    /**
     * The symbol used as a prefix when formatting positive numbers, e.g. "+".
     *
     * @serial
     * @see #getPositivePrefix
     */
    private String positivePrefix = "";

    /**
     * The symbol used as a suffix when formatting positive numbers. This is often an
     * empty string.
     *
     * @serial
     * @see #getPositiveSuffix
     */
    private String positiveSuffix = "";

    /**
     * The symbol used as a prefix when formatting negative numbers, e.g. "-".
     *
     * @serial
     * @see #getNegativePrefix
     */
    private String negativePrefix = "-";

    /**
     * The symbol used as a suffix when formatting negative numbers. This is often an
     * empty string.
     *
     * @serial
     * @see #getNegativeSuffix
     */
    private String negativeSuffix = "";

    /**
     * The prefix pattern for non-negative numbers. This variable corresponds to
     * <code>positivePrefix</code>.
     *
     * <p>This pattern is expanded by the method <code>expandAffix()</code> to
     * <code>positivePrefix</code> to update the latter to reflect changes in
     * <code>symbols</code>. If this variable is <code>null</code> then
     * <code>positivePrefix</code> is taken as a literal value that does not change when
     * <code>symbols</code> changes.  This variable is always <code>null</code> for
     * <code>DecimalFormat</code> objects older than stream version 2 restored from
     * stream.
     *
     * @serial
     */
    // [Richard/GCL]
    private String posPrefixPattern;

    /**
     * The suffix pattern for non-negative numbers. This variable corresponds to
     * <code>positiveSuffix</code>. This variable is analogous to
     * <code>posPrefixPattern</code>; see that variable for further documentation.
     *
     * @serial
     */
    // [Richard/GCL]
    private String posSuffixPattern;

    /**
     * The prefix pattern for negative numbers. This variable corresponds to
     * <code>negativePrefix</code>. This variable is analogous to
     * <code>posPrefixPattern</code>; see that variable for further documentation.
     *
     * @serial
     */
    // [Richard/GCL]
    private String negPrefixPattern;

    /**
     * The suffix pattern for negative numbers. This variable corresponds to
     * <code>negativeSuffix</code>. This variable is analogous to
     * <code>posPrefixPattern</code>; see that variable for further documentation.
     *
     * @serial
     */
    // [Richard/GCL]
    private String negSuffixPattern;

    /**
     * Formatter for ChoiceFormat-based currency names. If this field is not null, then
     * delegate to it to format currency symbols.
     *
     * @since ICU 2.6
     */
    private ChoiceFormat currencyChoice;

    /**
     * The multiplier for use in percent, permill, etc.
     *
     * @serial
     * @see #getMultiplier
     */
    private int multiplier = 1;

    /**
     * The number of digits between grouping separators in the integer portion of a
     * number. Must be greater than 0 if <code>NumberFormat.groupingUsed</code> is true.
     *
     * @serial
     * @see #getGroupingSize
     * @see NumberFormat#isGroupingUsed
     */
    private byte groupingSize = 3; // invariant, > 0 if useThousands

    /**
     * The secondary grouping size. This is only used for Hindi numerals, which use a
     * primary grouping of 3 and a secondary grouping of 2, e.g., "12,34,567". If this
     * value is less than 1, then secondary grouping is equal to the primary grouping.
     *
     */
    private byte groupingSize2 = 0;

    /**
     * If true, forces the decimal separator to always appear in a formatted number, even
     * if the fractional part of the number is zero.
     *
     * @serial
     * @see #isDecimalSeparatorAlwaysShown
     */
    private boolean decimalSeparatorAlwaysShown = false;

    /**
     * The <code>DecimalFormatSymbols</code> object used by this format. It contains the
     * symbols used to format numbers, e.g. the grouping separator, decimal separator, and
     * so on.
     *
     * @serial
     * @see #setDecimalFormatSymbols
     * @see DecimalFormatSymbols
     */
    private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();

    /**
     * True to use significant digits rather than integer and fraction digit counts.
     *
     * @serial
     * @since ICU 3.0
     */
    private boolean useSignificantDigits = false;

    /**
     * The minimum number of significant digits to show. Must be >= 1 and <=
     * maxSignificantDigits. Ignored unless useSignificantDigits == true.
     *
     * @serial
     * @since ICU 3.0
     */
    private int minSignificantDigits = 1;

    /**
     * The maximum number of significant digits to show. Must be >=
     * minSignficantDigits. Ignored unless useSignificantDigits == true.
     *
     * @serial
     * @since ICU 3.0
     */
    private int maxSignificantDigits = 6;

    /**
     * True to force the use of exponential (i.e. scientific) notation
     * when formatting numbers.
     *
     *<p> Note that the JDK 1.2 public API provides no way to set this
     * field, even though it is supported by the implementation and
     * the stream format. The intent is that this will be added to the
     * API in the future.
     *
     * @serial
     */
    private boolean useExponentialNotation; // Newly persistent in JDK 1.2

    /**
     * The minimum number of digits used to display the exponent when a number is
     * formatted in exponential notation.  This field is ignored if
     * <code>useExponentialNotation</code> is not true.
     *
     * <p>Note that the JDK 1.2 public API provides no way to set this field, even though
     * it is supported by the implementation and the stream format. The intent is that
     * this will be added to the API in the future.
     *
     * @serial
     */
    private byte minExponentDigits; // Newly persistent in JDK 1.2

    /**
     * If true, the exponent is always prefixed with either the plus sign or the minus
     * sign. Otherwise, only negative exponents are prefixed with the minus sign. This has
     * no effect unless <code>useExponentialNotation</code> is true.
     *
     * @serial
     * @since AlphaWorks NumberFormat
     */
    private boolean exponentSignAlwaysShown = false;

    /**
     * The value to which numbers are rounded during formatting. For example, if the
     * rounding increment is 0.05, then 13.371 would be formatted as 13.350, assuming 3
     * fraction digits. Has the value <code>null</code> if rounding is not in effect, or a
     * positive value if rounding is in effect. Default value <code>null</code>.
     *
     * @serial
     * @since AlphaWorks NumberFormat
     */
    // Note: this is kept in sync with roundingIncrementICU.
    // it is only kept around to avoid a conversion when formatting a java.math.BigDecimal
    private java.math.BigDecimal roundingIncrement = null;

    /**
     * The value to which numbers are rounded during formatting. For example, if the
     * rounding increment is 0.05, then 13.371 would be formatted as 13.350, assuming 3
     * fraction digits. Has the value <code>null</code> if rounding is not in effect, or a
     * positive value if rounding is in effect. Default value <code>null</code>. WARNING:
     * the roundingIncrement value is the one serialized.
     *
     * @serial
     * @since AlphaWorks NumberFormat
     */
    private transient BigDecimal roundingIncrementICU = null;

    /**
     * The rounding mode. This value controls any rounding operations which occur when
     * applying a rounding increment or when reducing the number of fraction digits to
     * satisfy a maximum fraction digits limit. The value may assume any of the
     * <code>BigDecimal</code> rounding mode values. Default value
     * <code>BigDecimal.ROUND_HALF_EVEN</code>.
     *
     * @serial
     * @since AlphaWorks NumberFormat
     */
    private int roundingMode = BigDecimal.ROUND_HALF_EVEN;

    /**
     * Operations on <code>BigDecimal</code> numbers are controlled by a {@link
     * MathContext} object, which provides the context (precision and other information)
     * for the operation. The default <code>MathContext</code> settings are
     * <code>digits=0, form=PLAIN, lostDigits=false, roundingMode=ROUND_HALF_UP</code>;
     * these settings perform fixed point arithmetic with unlimited precision, as defined
     * for the original BigDecimal class in Java 1.1 and Java 1.2
     */
    // context for plain unlimited math
    private MathContext mathContext = new MathContext(0, MathContext.PLAIN);

    /**
     * The padded format width, or zero if there is no padding. Must be >= 0. Default
     * value zero.
     *
     * @serial
     * @since AlphaWorks NumberFormat
     */
    private int formatWidth = 0;

    /**
     * The character used to pad the result of format to <code>formatWidth</code>, if
     * padding is in effect. Default value ' '.
     *
     * @serial
     * @since AlphaWorks NumberFormat
     */
    private char pad = ' ';

    /**
     * The position in the string at which the <code>pad</code> character will be
     * inserted, if padding is in effect.  Must have a value from
     * <code>PAD_BEFORE_PREFIX</code> to <code>PAD_AFTER_SUFFIX</code>. Default value
     * <code>PAD_BEFORE_PREFIX</code>.
     *
     * @serial
     * @since AlphaWorks NumberFormat
     */
    private int padPosition = PAD_BEFORE_PREFIX;

    /**
     * True if {@link #parse(String, ParsePosition)} to return BigDecimal rather than
     * Long, Double or BigDecimal except special values. This property is introduced for
     * J2SE 5 compatibility support.
     *
     * @serial
     * @since ICU 3.6
     * @see #setParseBigDecimal(boolean)
     * @see #isParseBigDecimal()
     */
    private boolean parseBigDecimal = false;

    // ----------------------------------------------------------------------

    static final int currentSerialVersion = 3;

    /**
     * The internal serial version which says which version was written Possible values
     * are:
     *
     * <ul>
     *
     * <li><b>0</b> (default): versions before JDK 1.2
     *
     * <li><b>1</b>: version from JDK 1.2 and later, which includes the two new fields
     * <code>useExponentialNotation</code> and <code>minExponentDigits</code>.
     *
     * <li><b>2</b>: version on AlphaWorks, which adds roundingMode, formatWidth, pad,
     * padPosition, exponentSignAlwaysShown, roundingIncrement.
     *
     * <li><b>3</b>: ICU 2.2. Adds currency object.
     *
     * </ul>
     *
     * @serial
     */
    private int serialVersionOnStream = currentSerialVersion;

    // ----------------------------------------------------------------------
    // CONSTANTS
    // ----------------------------------------------------------------------

    /**
     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
     * specify pad characters inserted before the prefix.
     *
     * @see #setPadPosition
     * @see #getPadPosition
     * @see #PAD_AFTER_PREFIX
     * @see #PAD_BEFORE_SUFFIX
     * @see #PAD_AFTER_SUFFIX
     * @stable ICU 2.0
     */
    public static final int PAD_BEFORE_PREFIX = 0;

    /**
     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
     * specify pad characters inserted after the prefix.
     *
     * @see #setPadPosition
     * @see #getPadPosition
     * @see #PAD_BEFORE_PREFIX
     * @see #PAD_BEFORE_SUFFIX
     * @see #PAD_AFTER_SUFFIX
     * @stable ICU 2.0
     */
    public static final int PAD_AFTER_PREFIX = 1;

    /**
     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
     * specify pad characters inserted before the suffix.
     *
     * @see #setPadPosition
     * @see #getPadPosition
     * @see #PAD_BEFORE_PREFIX
     * @see #PAD_AFTER_PREFIX
     * @see #PAD_AFTER_SUFFIX
     * @stable ICU 2.0
     */
    public static final int PAD_BEFORE_SUFFIX = 2;

    /**
     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
     * specify pad characters inserted after the suffix.
     *
     * @see #setPadPosition
     * @see #getPadPosition
     * @see #PAD_BEFORE_PREFIX
     * @see #PAD_AFTER_PREFIX
     * @see #PAD_BEFORE_SUFFIX
     * @stable ICU 2.0
     */
    public static final int PAD_AFTER_SUFFIX = 3;

    // Constants for characters used in programmatic (unlocalized) patterns.
    static final char PATTERN_ZERO_DIGIT = '0';
    static final char PATTERN_ONE_DIGIT = '1';
    static final char PATTERN_TWO_DIGIT = '2';
    static final char PATTERN_THREE_DIGIT = '3';
    static final char PATTERN_FOUR_DIGIT = '4';
    static final char PATTERN_FIVE_DIGIT = '5';
    static final char PATTERN_SIX_DIGIT = '6';
    static final char PATTERN_SEVEN_DIGIT = '7';
    static final char PATTERN_EIGHT_DIGIT = '8';
    static final char PATTERN_NINE_DIGIT = '9';
    static final char PATTERN_GROUPING_SEPARATOR = ',';
    static final char PATTERN_DECIMAL_SEPARATOR = '.';
    static final char PATTERN_DIGIT = '#';
    static final char PATTERN_SIGNIFICANT_DIGIT = '@';
    static final char PATTERN_EXPONENT = 'E';
    static final char PATTERN_PLUS_SIGN = '+';

    // Affix
    private static final char PATTERN_PER_MILLE = '\u2030';
    private static final char PATTERN_PERCENT = '%';
    static final char PATTERN_PAD_ESCAPE = '*';
    /**
     * Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) [Richard/GCL]
     */
    private static final char PATTERN_MINUS = '-';

    // Other
    private static final char PATTERN_SEPARATOR = ';';

    // Pad escape is package private to allow access by DecimalFormatSymbols.
    // Also plus sign. Also exponent.

    /**
     * The CURRENCY_SIGN is the standard Unicode symbol for currency. It is used in
     * patterns and substitued with either the currency symbol, or if it is doubled, with
     * the international currency symbol. If the CURRENCY_SIGN is seen in a pattern, then
     * the decimal separator is replaced with the monetary decimal separator.
     *
     * The CURRENCY_SIGN is not localized.
     */
    private static final char CURRENCY_SIGN = '\u00A4';

    private static final char QUOTE = '\'';

    /**
     * Upper limit on integer and fraction digits for a Java double [Richard/GCL]
     */
    static final int DOUBLE_INTEGER_DIGITS = 309;
    static final int DOUBLE_FRACTION_DIGITS = 340;

    /**
     * When someone turns on scientific mode, we assume that more than this number of
     * digits is due to flipping from some other mode that didn't restrict the maximum,
     * and so we force 1 integer digit. We don't bother to track and see if someone is
     * using exponential notation with more than this number, it wouldn't make sense
     * anyway, and this is just to make sure that someone turning on scientific mode with
     * default settings doesn't end up with lots of zeroes.
     */
    static final int MAX_SCIENTIFIC_INTEGER_DIGITS = 8;

    // Proclaim JDK 1.1 serial compatibility.
    private static final long serialVersionUID = 864413376551465018L;

    private ArrayList<FieldPosition> attributes = new ArrayList<FieldPosition>();

    // The following are used in currency format

    // -- triple currency sign char array
    // private static final char[] tripleCurrencySign = {0xA4, 0xA4, 0xA4};
    // -- triple currency sign string
    // private static final String tripleCurrencyStr = new String(tripleCurrencySign);
    //
    // -- default currency plural pattern char array
    // private static final char[] defaultCurrencyPluralPatternChar =
    //   {0, '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4};
    // -- default currency plural pattern string
    // private static final String defaultCurrencyPluralPattern =
    //     new String(defaultCurrencyPluralPatternChar);

    // pattern used in this formatter
    private String formatPattern = "";
    // style is only valid when decimal formatter is constructed by
    // DecimalFormat(pattern, decimalFormatSymbol, style)
    private int style = NumberFormat.NUMBERSTYLE;
    /**
     * Represents whether this is a currency format, and which currency format style. 0:
     * not currency format type; 1: currency style -- symbol name, such as "$" for US
     * dollar. 2: currency style -- ISO name, such as USD for US dollar. 3: currency style
     * -- plural long name, such as "US Dollar" for "1.00 US Dollar", or "US Dollars" for
     * "3.00 US Dollars".
     */
    private int currencySignCount = CURRENCY_SIGN_COUNT_ZERO;

    /**
     * For parsing purposes, we need to remember all prefix patterns and suffix patterns
     * of every currency format pattern, including the pattern of the default currency
     * style, ISO currency style, and plural currency style. The patterns are set through
     * applyPattern. The following are used to represent the affix patterns in currency
     * plural formats.
     */
    private static final class AffixForCurrency {
        // negative prefix pattern
        private String negPrefixPatternForCurrency = null;
        // negative suffix pattern
        private String negSuffixPatternForCurrency = null;
        // positive prefix pattern
        private String posPrefixPatternForCurrency = null;
        // positive suffix pattern
        private String posSuffixPatternForCurrency = null;
        private final int patternType;

        public AffixForCurrency(String negPrefix, String negSuffix, String posPrefix,
                                String posSuffix, int type) {
            negPrefixPatternForCurrency = negPrefix;
            negSuffixPatternForCurrency = negSuffix;
            posPrefixPatternForCurrency = posPrefix;
            posSuffixPatternForCurrency = posSuffix;
            patternType = type;
        }

        public String getNegPrefix() {
            return negPrefixPatternForCurrency;
        }

        public String getNegSuffix() {
            return negSuffixPatternForCurrency;
        }

        public String getPosPrefix() {
            return posPrefixPatternForCurrency;
        }

        public String getPosSuffix() {
            return posSuffixPatternForCurrency;
        }

        public int getPatternType() {
            return patternType;
        }
    }

    // Affix pattern set for currency.  It is a set of AffixForCurrency, each element of
    // the set saves the negative prefix, negative suffix, positive prefix, and positive
    // suffix of a pattern.
    private transient Set<AffixForCurrency> affixPatternsForCurrency = null;

    // For currency parsing. Since currency parsing needs to parse against all currency
    // patterns, before the parsing, we need to set up the affix patterns for all currencies.
    private transient boolean isReadyForParsing = false;

    // Information needed for DecimalFormat to format/parse currency plural.
    private CurrencyPluralInfo currencyPluralInfo = null;

    /**
     * Unit is an immutable class for the textual representation of a unit, in
     * particular its prefix and suffix.
     *
     * @author rocketman
     *
     */
    static class Unit {
        private final String prefix;
        private final String suffix;

        public Unit(String prefix, String suffix) {
            this.prefix = prefix;
            this.suffix = suffix;
        }

        public void writeSuffix(StringBuffer toAppendTo) {
            toAppendTo.append(suffix);
        }

        public void writePrefix(StringBuffer toAppendTo) {
            toAppendTo.append(prefix);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof Unit)) {
                return false;
            }
            Unit other = (Unit) obj;
            return prefix.equals(other.prefix) && suffix.equals(other.suffix);
        }
        @Override
        public String toString() {
            return prefix + "/" + suffix;
        }
    }

    static final Unit NULL_UNIT = new Unit("", "");

    // Note about rounding implementation
    //
    // The original design intended to skip rounding operation when roundingIncrement is not
    // set. However, rounding may need to occur when fractional digits exceed the width of
    // fractional part of pattern.
    //
    // DigitList class has built-in rounding mechanism, using ROUND_HALF_EVEN. This implementation
    // forces non-null roundingIncrement if the setting is other than ROUND_HALF_EVEN, otherwise,
    // when rounding occurs in DigitList by pattern's fractional digits' width, the result
    // does not match the rounding mode.
    //
    // Ideally, all rounding operation should be done in one place like ICU4C trunk does
    // (ICU4C rounding implementation was rewritten recently). This is intrim implemetation
    // to fix various issues. In the future, we should entire implementation of rounding
    // in this class, like ICU4C did.
    //
    // Once we fully implement rounding logic in DigitList, then following fields and methods
    // should be gone.

    private transient BigDecimal actualRoundingIncrementICU = null;
    private transient java.math.BigDecimal actualRoundingIncrement = null;

    /*
     * The actual rounding increment as a double.
     */
    private transient double roundingDouble = 0.0;

    /*
     * If the roundingDouble is the reciprocal of an integer (the most common case!), this
     * is set to be that integer.  Otherwise it is 0.0.
     */
    private transient double roundingDoubleReciprocal = 0.0;

    /*
     * Set roundingDouble, roundingDoubleReciprocal and actualRoundingIncrement
     * based on rounding mode and width of fractional digits. Whenever setting affecting
     * rounding mode, rounding increment and maximum width of fractional digits, then
     * this method must be called.
     * 
     * roundingIncrementICU is the field storing the custom rounding increment value,
     * while actual rounding increment could be larger.
     */
    private void resetActualRounding() {
        if (roundingIncrementICU != null) {
            BigDecimal byWidth = getMaximumFractionDigits() > 0 ?
                    BigDecimal.ONE.movePointLeft(getMaximumFractionDigits()) : BigDecimal.ONE;
            if (roundingIncrementICU.compareTo(byWidth) >= 0) {
                actualRoundingIncrementICU = roundingIncrementICU;
            } else {
                actualRoundingIncrementICU = byWidth.equals(BigDecimal.ONE) ? null : byWidth;
            }
        } else {
            if (roundingMode == BigDecimal.ROUND_HALF_EVEN) {
                actualRoundingIncrementICU = null;
            } else {
                if (getMaximumFractionDigits() > 0) {
                    actualRoundingIncrementICU = BigDecimal.ONE.movePointLeft(getMaximumFractionDigits());
                }
            }
        }

        if (actualRoundingIncrementICU == null) {
            setRoundingDouble(0.0d);
            actualRoundingIncrement = null;
        } else {
            setRoundingDouble(actualRoundingIncrementICU.doubleValue());
            actualRoundingIncrement = actualRoundingIncrementICU.toBigDecimal();
        }
    }

    static final double roundingIncrementEpsilon = 0.000000001;

    private void setRoundingDouble(double newValue) {
        roundingDouble = newValue;
        if (roundingDouble > 0.0d) {
            double rawRoundedReciprocal = 1.0d / roundingDouble;
            roundingDoubleReciprocal = Math.rint(rawRoundedReciprocal);
            if (Math.abs(rawRoundedReciprocal - roundingDoubleReciprocal) > roundingIncrementEpsilon) {
                roundingDoubleReciprocal = 0.0d;
            }
        } else {
            roundingDoubleReciprocal = 0.0d;
        }
    }
}

// eof
