Home | History | Annotate | Download | only in i18n
      1 //  2017 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 
      4 #include "unicode/utypes.h"
      5 
      6 #if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT
      7 #ifndef __NUMBER_DECIMALQUANTITY_H__
      8 #define __NUMBER_DECIMALQUANTITY_H__
      9 
     10 #include <cstdint>
     11 #include "unicode/umachine.h"
     12 #include "decNumber.h"
     13 #include "standardplural.h"
     14 #include "plurrule_impl.h"
     15 #include "number_types.h"
     16 
     17 U_NAMESPACE_BEGIN namespace number {
     18 namespace impl {
     19 
     20 /**
     21  * An class for representing a number to be processed by the decimal formatting pipeline. Includes
     22  * methods for rounding, plural rules, and decimal digit extraction.
     23  *
     24  * <p>By design, this is NOT IMMUTABLE and NOT THREAD SAFE. It is intended to be an intermediate
     25  * object holding state during a pass through the decimal formatting pipeline.
     26  *
     27  * <p>Represents numbers and digit display properties using Binary Coded Decimal (BCD).
     28  *
     29  * <p>Java has multiple implementations for testing, but C++ has only one implementation.
     30  */
     31 class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory {
     32   public:
     33     /** Copy constructor. */
     34     DecimalQuantity(const DecimalQuantity &other);
     35 
     36     DecimalQuantity();
     37 
     38     ~DecimalQuantity();
     39 
     40     /**
     41      * Sets this instance to be equal to another instance.
     42      *
     43      * @param other The instance to copy from.
     44      */
     45     DecimalQuantity &operator=(const DecimalQuantity &other);
     46 
     47     /**
     48      * Sets the minimum and maximum integer digits that this {@link DecimalQuantity} should generate.
     49      * This method does not perform rounding.
     50      *
     51      * @param minInt The minimum number of integer digits.
     52      * @param maxInt The maximum number of integer digits.
     53      */
     54     void setIntegerLength(int32_t minInt, int32_t maxInt);
     55 
     56     /**
     57      * Sets the minimum and maximum fraction digits that this {@link DecimalQuantity} should generate.
     58      * This method does not perform rounding.
     59      *
     60      * @param minFrac The minimum number of fraction digits.
     61      * @param maxFrac The maximum number of fraction digits.
     62      */
     63     void setFractionLength(int32_t minFrac, int32_t maxFrac);
     64 
     65     /**
     66      * Rounds the number to a specified interval, such as 0.05.
     67      *
     68      * <p>If rounding to a power of ten, use the more efficient {@link #roundToMagnitude} instead.
     69      *
     70      * @param roundingIncrement The increment to which to round.
     71      * @param mathContext The {@link RoundingMode} to use if rounding is necessary.
     72      */
     73     void roundToIncrement(double roundingIncrement, RoundingMode roundingMode,
     74                           int32_t minMaxFrac, UErrorCode& status);
     75 
     76     /**
     77      * Rounds the number to a specified magnitude (power of ten).
     78      *
     79      * @param roundingMagnitude The power of ten to which to round. For example, a value of -2 will
     80      *     round to 2 decimal places.
     81      * @param mathContext The {@link RoundingMode} to use if rounding is necessary.
     82      */
     83     void roundToMagnitude(int32_t magnitude, RoundingMode roundingMode, UErrorCode& status);
     84 
     85     /**
     86      * Rounds the number to an infinite number of decimal points. This has no effect except for
     87      * forcing the double in {@link DecimalQuantity_AbstractBCD} to adopt its exact representation.
     88      */
     89     void roundToInfinity();
     90 
     91     /**
     92      * Multiply the internal value.
     93      *
     94      * @param multiplicand The value by which to multiply.
     95      */
     96     void multiplyBy(int32_t multiplicand);
     97 
     98     /**
     99      * Scales the number by a power of ten. For example, if the value is currently "1234.56", calling
    100      * this method with delta=-3 will change the value to "1.23456".
    101      *
    102      * @param delta The number of magnitudes of ten to change by.
    103      */
    104     void adjustMagnitude(int32_t delta);
    105 
    106     /**
    107      * @return The power of ten corresponding to the most significant nonzero digit.
    108      * The number must not be zero.
    109      */
    110     int32_t getMagnitude() const;
    111 
    112     /** @return Whether the value represented by this {@link DecimalQuantity} is zero. */
    113     bool isZero() const;
    114 
    115     /** @return Whether the value represented by this {@link DecimalQuantity} is less than zero. */
    116     bool isNegative() const;
    117 
    118     /** @return Whether the value represented by this {@link DecimalQuantity} is infinite. */
    119     bool isInfinite() const U_OVERRIDE;
    120 
    121     /** @return Whether the value represented by this {@link DecimalQuantity} is not a number. */
    122     bool isNaN() const U_OVERRIDE;
    123 
    124     int64_t toLong() const;
    125 
    126     int64_t toFractionLong(bool includeTrailingZeros) const;
    127 
    128     /** @return The value contained in this {@link DecimalQuantity} approximated as a double. */
    129     double toDouble() const;
    130 
    131     DecimalQuantity &setToInt(int32_t n);
    132 
    133     DecimalQuantity &setToLong(int64_t n);
    134 
    135     DecimalQuantity &setToDouble(double n);
    136 
    137     /** decNumber is similar to BigDecimal in Java. */
    138 
    139     DecimalQuantity &setToDecNumber(StringPiece n);
    140 
    141     /**
    142      * Appends a digit, optionally with one or more leading zeros, to the end of the value represented
    143      * by this DecimalQuantity.
    144      *
    145      * <p>The primary use of this method is to construct numbers during a parsing loop. It allows
    146      * parsing to take advantage of the digit list infrastructure primarily designed for formatting.
    147      *
    148      * @param value The digit to append.
    149      * @param leadingZeros The number of zeros to append before the digit. For example, if the value
    150      *     in this instance starts as 12.3, and you append a 4 with 1 leading zero, the value becomes
    151      *     12.304.
    152      * @param appendAsInteger If true, increase the magnitude of existing digits to make room for the
    153      *     new digit. If false, append to the end like a fraction digit. If true, there must not be
    154      *     any fraction digits already in the number.
    155      * @internal
    156      * @deprecated This API is ICU internal only.
    157      */
    158     void appendDigit(int8_t value, int32_t leadingZeros, bool appendAsInteger);
    159 
    160     /**
    161      * Computes the plural form for this number based on the specified set of rules.
    162      *
    163      * @param rules A {@link PluralRules} object representing the set of rules.
    164      * @return The {@link StandardPlural} according to the PluralRules. If the plural form is not in
    165      *     the set of standard plurals, {@link StandardPlural#OTHER} is returned instead.
    166      */
    167     StandardPlural::Form getStandardPlural(const PluralRules *rules) const;
    168 
    169     double getPluralOperand(PluralOperand operand) const U_OVERRIDE;
    170 
    171     /**
    172      * Gets the digit at the specified magnitude. For example, if the represented number is 12.3,
    173      * getDigit(-1) returns 3, since 3 is the digit corresponding to 10^-1.
    174      *
    175      * @param magnitude The magnitude of the digit.
    176      * @return The digit at the specified magnitude.
    177      */
    178     int8_t getDigit(int32_t magnitude) const;
    179 
    180     /**
    181      * Gets the largest power of ten that needs to be displayed. The value returned by this function
    182      * will be bounded between minInt and maxInt.
    183      *
    184      * @return The highest-magnitude digit to be displayed.
    185      */
    186     int32_t getUpperDisplayMagnitude() const;
    187 
    188     /**
    189      * Gets the smallest power of ten that needs to be displayed. The value returned by this function
    190      * will be bounded between -minFrac and -maxFrac.
    191      *
    192      * @return The lowest-magnitude digit to be displayed.
    193      */
    194     int32_t getLowerDisplayMagnitude() const;
    195 
    196     int32_t fractionCount() const;
    197 
    198     int32_t fractionCountWithoutTrailingZeros() const;
    199 
    200     void clear();
    201 
    202     /** This method is for internal testing only. */
    203     uint64_t getPositionFingerprint() const;
    204 
    205 //    /**
    206 //     * If the given {@link FieldPosition} is a {@link UFieldPosition}, populates it with the fraction
    207 //     * length and fraction long value. If the argument is not a {@link UFieldPosition}, nothing
    208 //     * happens.
    209 //     *
    210 //     * @param fp The {@link UFieldPosition} to populate.
    211 //     */
    212 //    void populateUFieldPosition(FieldPosition fp);
    213 
    214     /**
    215      * Checks whether the bytes stored in this instance are all valid. For internal unit testing only.
    216      *
    217      * @return An error message if this instance is invalid, or null if this instance is healthy.
    218      */
    219     const char16_t* checkHealth() const;
    220 
    221     UnicodeString toString() const;
    222 
    223     /* Returns the string in exponential notation. */
    224     UnicodeString toNumberString() const;
    225 
    226     /* Returns the string without exponential notation. Slightly slower than toNumberString(). */
    227     UnicodeString toPlainString() const;
    228 
    229     /** Visible for testing */
    230     inline bool isUsingBytes() { return usingBytes; }
    231 
    232     /** Visible for testing */
    233     inline bool isExplicitExactDouble() { return explicitExactDouble; };
    234 
    235   private:
    236     /**
    237      * The power of ten corresponding to the least significant digit in the BCD. For example, if this
    238      * object represents the number "3.14", the BCD will be "0x314" and the scale will be -2.
    239      *
    240      * <p>Note that in {@link java.math.BigDecimal}, the scale is defined differently: the number of
    241      * digits after the decimal place, which is the negative of our definition of scale.
    242      */
    243     int32_t scale;
    244 
    245     /**
    246      * The number of digits in the BCD. For example, "1007" has BCD "0x1007" and precision 4. The
    247      * maximum precision is 16 since a long can hold only 16 digits.
    248      *
    249      * <p>This value must be re-calculated whenever the value in bcd changes by using {@link
    250      * #computePrecisionAndCompact()}.
    251      */
    252     int32_t precision;
    253 
    254     /**
    255      * A bitmask of properties relating to the number represented by this object.
    256      *
    257      * @see #NEGATIVE_FLAG
    258      * @see #INFINITY_FLAG
    259      * @see #NAN_FLAG
    260      */
    261     int8_t flags;
    262 
    263     // The following three fields relate to the double-to-ascii fast path algorithm.
    264     // When a double is given to DecimalQuantityBCD, it is converted to using a fast algorithm. The
    265     // fast algorithm guarantees correctness to only the first ~12 digits of the double. The process
    266     // of rounding the number ensures that the converted digits are correct, falling back to a slow-
    267     // path algorithm if required.  Therefore, if a DecimalQuantity is constructed from a double, it
    268     // is *required* that roundToMagnitude(), roundToIncrement(), or roundToInfinity() is called. If
    269     // you don't round, assertions will fail in certain other methods if you try calling them.
    270 
    271     /**
    272      * Whether the value in the BCD comes from the double fast path without having been rounded to
    273      * ensure correctness
    274      */
    275     UBool isApproximate;
    276 
    277     /**
    278      * The original number provided by the user and which is represented in BCD. Used when we need to
    279      * re-compute the BCD for an exact double representation.
    280      */
    281     double origDouble;
    282 
    283     /**
    284      * The change in magnitude relative to the original double. Used when we need to re-compute the
    285      * BCD for an exact double representation.
    286      */
    287     int32_t origDelta;
    288 
    289     // Four positions: left optional '(', left required '[', right required ']', right optional ')'.
    290     // These four positions determine which digits are displayed in the output string.  They do NOT
    291     // affect rounding.  These positions are internal-only and can be specified only by the public
    292     // endpoints like setFractionLength, setIntegerLength, and setSignificantDigits, among others.
    293     //
    294     //   * Digits between lReqPos and rReqPos are in the "required zone" and are always displayed.
    295     //   * Digits between lOptPos and rOptPos but outside the required zone are in the "optional zone"
    296     //     and are displayed unless they are trailing off the left or right edge of the number and
    297     //     have a numerical value of zero.  In order to be "trailing", the digits need to be beyond
    298     //     the decimal point in their respective directions.
    299     //   * Digits outside of the "optional zone" are never displayed.
    300     //
    301     // See the table below for illustrative examples.
    302     //
    303     // +---------+---------+---------+---------+------------+------------------------+--------------+
    304     // | lOptPos | lReqPos | rReqPos | rOptPos |   number   |        positions       | en-US string |
    305     // +---------+---------+---------+---------+------------+------------------------+--------------+
    306     // |    5    |    2    |   -1    |   -5    |   1234.567 |     ( 12[34.5]67  )    |   1,234.567  |
    307     // |    3    |    2    |   -1    |   -5    |   1234.567 |      1(2[34.5]67  )    |     234.567  |
    308     // |    3    |    2    |   -1    |   -2    |   1234.567 |      1(2[34.5]6)7      |     234.56   |
    309     // |    6    |    4    |    2    |   -5    | 123456789. |  123(45[67]89.     )   | 456,789.     |
    310     // |    6    |    4    |    2    |    1    | 123456789. |     123(45[67]8)9.     | 456,780.     |
    311     // |   -1    |   -1    |   -3    |   -4    | 0.123456   |     0.1([23]4)56       |        .0234 |
    312     // |    6    |    4    |   -2    |   -2    |     12.3   |     (  [  12.3 ])      |    0012.30   |
    313     // +---------+---------+---------+---------+------------+------------------------+--------------+
    314     //
    315     int32_t lOptPos = INT32_MAX;
    316     int32_t lReqPos = 0;
    317     int32_t rReqPos = 0;
    318     int32_t rOptPos = INT32_MIN;
    319 
    320     /**
    321      * The BCD of the 16 digits of the number represented by this object. Every 4 bits of the long map
    322      * to one digit. For example, the number "12345" in BCD is "0x12345".
    323      *
    324      * <p>Whenever bcd changes internally, {@link #compact()} must be called, except in special cases
    325      * like setting the digit to zero.
    326      */
    327     union {
    328         struct {
    329             int8_t *ptr;
    330             int32_t len;
    331         } bcdBytes;
    332         uint64_t bcdLong;
    333     } fBCD;
    334 
    335     bool usingBytes = false;
    336 
    337     /**
    338      * Whether this {@link DecimalQuantity} has been explicitly converted to an exact double. true if
    339      * backed by a double that was explicitly converted via convertToAccurateDouble; false otherwise.
    340      * Used for testing.
    341      */
    342     bool explicitExactDouble = false;
    343 
    344     /**
    345      * Returns a single digit from the BCD list. No internal state is changed by calling this method.
    346      *
    347      * @param position The position of the digit to pop, counted in BCD units from the least
    348      *     significant digit. If outside the range supported by the implementation, zero is returned.
    349      * @return The digit at the specified location.
    350      */
    351     int8_t getDigitPos(int32_t position) const;
    352 
    353     /**
    354      * Sets the digit in the BCD list. This method only sets the digit; it is the caller's
    355      * responsibility to call {@link #compact} after setting the digit.
    356      *
    357      * @param position The position of the digit to pop, counted in BCD units from the least
    358      *     significant digit. If outside the range supported by the implementation, an AssertionError
    359      *     is thrown.
    360      * @param value The digit to set at the specified location.
    361      */
    362     void setDigitPos(int32_t position, int8_t value);
    363 
    364     /**
    365      * Adds zeros to the end of the BCD list. This will result in an invalid BCD representation; it is
    366      * the caller's responsibility to do further manipulation and then call {@link #compact}.
    367      *
    368      * @param numDigits The number of zeros to add.
    369      */
    370     void shiftLeft(int32_t numDigits);
    371 
    372     void shiftRight(int32_t numDigits);
    373 
    374     /**
    375      * Sets the internal representation to zero. Clears any values stored in scale, precision,
    376      * hasDouble, origDouble, origDelta, and BCD data.
    377      */
    378     void setBcdToZero();
    379 
    380     /**
    381      * Sets the internal BCD state to represent the value in the given int. The int is guaranteed to
    382      * be either positive. The internal state is guaranteed to be empty when this method is called.
    383      *
    384      * @param n The value to consume.
    385      */
    386     void readIntToBcd(int32_t n);
    387 
    388     /**
    389      * Sets the internal BCD state to represent the value in the given long. The long is guaranteed to
    390      * be either positive. The internal state is guaranteed to be empty when this method is called.
    391      *
    392      * @param n The value to consume.
    393      */
    394     void readLongToBcd(int64_t n);
    395 
    396     void readDecNumberToBcd(decNumber *dn);
    397 
    398     void copyBcdFrom(const DecimalQuantity &other);
    399 
    400     /**
    401      * Removes trailing zeros from the BCD (adjusting the scale as required) and then computes the
    402      * precision. The precision is the number of digits in the number up through the greatest nonzero
    403      * digit.
    404      *
    405      * <p>This method must always be called when bcd changes in order for assumptions to be correct in
    406      * methods like {@link #fractionCount()}.
    407      */
    408     void compact();
    409 
    410     void _setToInt(int32_t n);
    411 
    412     void _setToLong(int64_t n);
    413 
    414     void _setToDoubleFast(double n);
    415 
    416     void _setToDecNumber(decNumber *n);
    417 
    418     void convertToAccurateDouble();
    419 
    420     double toDoubleFromOriginal() const;
    421 
    422     /** Ensure that a byte array of at least 40 digits is allocated. */
    423     void ensureCapacity();
    424 
    425     void ensureCapacity(int32_t capacity);
    426 
    427     /** Switches the internal storage mechanism between the 64-bit long and the byte array. */
    428     void switchStorage();
    429 };
    430 
    431 } // namespace impl
    432 } // namespace number
    433 U_NAMESPACE_END
    434 
    435 
    436 #endif //__NUMBER_DECIMALQUANTITY_H__
    437 
    438 #endif /* #if !UCONFIG_NO_FORMATTING */
    439