12e5b6d6dSopenharmony_ci// © 2017 and later: Unicode, Inc. and others. 22e5b6d6dSopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html 32e5b6d6dSopenharmony_ci 42e5b6d6dSopenharmony_ci#include "unicode/utypes.h" 52e5b6d6dSopenharmony_ci 62e5b6d6dSopenharmony_ci#if !UCONFIG_NO_FORMATTING 72e5b6d6dSopenharmony_ci#ifndef __NUMBER_DECIMALQUANTITY_H__ 82e5b6d6dSopenharmony_ci#define __NUMBER_DECIMALQUANTITY_H__ 92e5b6d6dSopenharmony_ci 102e5b6d6dSopenharmony_ci#include <cstdint> 112e5b6d6dSopenharmony_ci#include "unicode/umachine.h" 122e5b6d6dSopenharmony_ci#include "standardplural.h" 132e5b6d6dSopenharmony_ci#include "plurrule_impl.h" 142e5b6d6dSopenharmony_ci#include "number_types.h" 152e5b6d6dSopenharmony_ci 162e5b6d6dSopenharmony_ciU_NAMESPACE_BEGIN namespace number { 172e5b6d6dSopenharmony_cinamespace impl { 182e5b6d6dSopenharmony_ci 192e5b6d6dSopenharmony_ci// Forward-declare (maybe don't want number_utils.h included here): 202e5b6d6dSopenharmony_ciclass DecNum; 212e5b6d6dSopenharmony_ci 222e5b6d6dSopenharmony_ci/** 232e5b6d6dSopenharmony_ci * A class for representing a number to be processed by the decimal formatting pipeline. Includes 242e5b6d6dSopenharmony_ci * methods for rounding, plural rules, and decimal digit extraction. 252e5b6d6dSopenharmony_ci * 262e5b6d6dSopenharmony_ci * <p>By design, this is NOT IMMUTABLE and NOT THREAD SAFE. It is intended to be an intermediate 272e5b6d6dSopenharmony_ci * object holding state during a pass through the decimal formatting pipeline. 282e5b6d6dSopenharmony_ci * 292e5b6d6dSopenharmony_ci * <p>Represents numbers and digit display properties using Binary Coded Decimal (BCD). 302e5b6d6dSopenharmony_ci * 312e5b6d6dSopenharmony_ci * <p>Java has multiple implementations for testing, but C++ has only one implementation. 322e5b6d6dSopenharmony_ci */ 332e5b6d6dSopenharmony_ciclass U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { 342e5b6d6dSopenharmony_ci public: 352e5b6d6dSopenharmony_ci /** Copy constructor. */ 362e5b6d6dSopenharmony_ci DecimalQuantity(const DecimalQuantity &other); 372e5b6d6dSopenharmony_ci 382e5b6d6dSopenharmony_ci /** Move constructor. */ 392e5b6d6dSopenharmony_ci DecimalQuantity(DecimalQuantity &&src) U_NOEXCEPT; 402e5b6d6dSopenharmony_ci 412e5b6d6dSopenharmony_ci DecimalQuantity(); 422e5b6d6dSopenharmony_ci 432e5b6d6dSopenharmony_ci ~DecimalQuantity() override; 442e5b6d6dSopenharmony_ci 452e5b6d6dSopenharmony_ci /** 462e5b6d6dSopenharmony_ci * Sets this instance to be equal to another instance. 472e5b6d6dSopenharmony_ci * 482e5b6d6dSopenharmony_ci * @param other The instance to copy from. 492e5b6d6dSopenharmony_ci */ 502e5b6d6dSopenharmony_ci DecimalQuantity &operator=(const DecimalQuantity &other); 512e5b6d6dSopenharmony_ci 522e5b6d6dSopenharmony_ci /** Move assignment */ 532e5b6d6dSopenharmony_ci DecimalQuantity &operator=(DecimalQuantity&& src) U_NOEXCEPT; 542e5b6d6dSopenharmony_ci 552e5b6d6dSopenharmony_ci /** 562e5b6d6dSopenharmony_ci * Sets the minimum integer digits that this {@link DecimalQuantity} should generate. 572e5b6d6dSopenharmony_ci * This method does not perform rounding. 582e5b6d6dSopenharmony_ci * 592e5b6d6dSopenharmony_ci * @param minInt The minimum number of integer digits. 602e5b6d6dSopenharmony_ci */ 612e5b6d6dSopenharmony_ci void setMinInteger(int32_t minInt); 622e5b6d6dSopenharmony_ci 632e5b6d6dSopenharmony_ci /** 642e5b6d6dSopenharmony_ci * Sets the minimum fraction digits that this {@link DecimalQuantity} should generate. 652e5b6d6dSopenharmony_ci * This method does not perform rounding. 662e5b6d6dSopenharmony_ci * 672e5b6d6dSopenharmony_ci * @param minFrac The minimum number of fraction digits. 682e5b6d6dSopenharmony_ci */ 692e5b6d6dSopenharmony_ci void setMinFraction(int32_t minFrac); 702e5b6d6dSopenharmony_ci 712e5b6d6dSopenharmony_ci /** 722e5b6d6dSopenharmony_ci * Truncates digits from the upper magnitude of the number in order to satisfy the 732e5b6d6dSopenharmony_ci * specified maximum number of integer digits. 742e5b6d6dSopenharmony_ci * 752e5b6d6dSopenharmony_ci * @param maxInt The maximum number of integer digits. 762e5b6d6dSopenharmony_ci */ 772e5b6d6dSopenharmony_ci void applyMaxInteger(int32_t maxInt); 782e5b6d6dSopenharmony_ci 792e5b6d6dSopenharmony_ci /** 802e5b6d6dSopenharmony_ci * Rounds the number to a specified interval, such as 0.05. 812e5b6d6dSopenharmony_ci * 822e5b6d6dSopenharmony_ci * <p>If rounding to a power of ten, use the more efficient {@link #roundToMagnitude} instead. 832e5b6d6dSopenharmony_ci * 842e5b6d6dSopenharmony_ci * @param increment The increment to which to round. 852e5b6d6dSopenharmony_ci * @param magnitude The power of 10 to which to round. 862e5b6d6dSopenharmony_ci * @param roundingMode The {@link RoundingMode} to use if rounding is necessary. 872e5b6d6dSopenharmony_ci */ 882e5b6d6dSopenharmony_ci void roundToIncrement( 892e5b6d6dSopenharmony_ci uint64_t increment, 902e5b6d6dSopenharmony_ci digits_t magnitude, 912e5b6d6dSopenharmony_ci RoundingMode roundingMode, 922e5b6d6dSopenharmony_ci UErrorCode& status); 932e5b6d6dSopenharmony_ci 942e5b6d6dSopenharmony_ci /** Removes all fraction digits. */ 952e5b6d6dSopenharmony_ci void truncate(); 962e5b6d6dSopenharmony_ci 972e5b6d6dSopenharmony_ci /** 982e5b6d6dSopenharmony_ci * Rounds the number to the nearest multiple of 5 at the specified magnitude. 992e5b6d6dSopenharmony_ci * For example, when magnitude == -2, this performs rounding to the nearest 0.05. 1002e5b6d6dSopenharmony_ci * 1012e5b6d6dSopenharmony_ci * @param magnitude The magnitude at which the digit should become either 0 or 5. 1022e5b6d6dSopenharmony_ci * @param roundingMode Rounding strategy. 1032e5b6d6dSopenharmony_ci */ 1042e5b6d6dSopenharmony_ci void roundToNickel(int32_t magnitude, RoundingMode roundingMode, UErrorCode& status); 1052e5b6d6dSopenharmony_ci 1062e5b6d6dSopenharmony_ci /** 1072e5b6d6dSopenharmony_ci * Rounds the number to a specified magnitude (power of ten). 1082e5b6d6dSopenharmony_ci * 1092e5b6d6dSopenharmony_ci * @param roundingMagnitude The power of ten to which to round. For example, a value of -2 will 1102e5b6d6dSopenharmony_ci * round to 2 decimal places. 1112e5b6d6dSopenharmony_ci * @param roundingMode The {@link RoundingMode} to use if rounding is necessary. 1122e5b6d6dSopenharmony_ci */ 1132e5b6d6dSopenharmony_ci void roundToMagnitude(int32_t magnitude, RoundingMode roundingMode, UErrorCode& status); 1142e5b6d6dSopenharmony_ci 1152e5b6d6dSopenharmony_ci /** 1162e5b6d6dSopenharmony_ci * Rounds the number to an infinite number of decimal points. This has no effect except for 1172e5b6d6dSopenharmony_ci * forcing the double in {@link DecimalQuantity_AbstractBCD} to adopt its exact representation. 1182e5b6d6dSopenharmony_ci */ 1192e5b6d6dSopenharmony_ci void roundToInfinity(); 1202e5b6d6dSopenharmony_ci 1212e5b6d6dSopenharmony_ci /** 1222e5b6d6dSopenharmony_ci * Multiply the internal value. Uses decNumber. 1232e5b6d6dSopenharmony_ci * 1242e5b6d6dSopenharmony_ci * @param multiplicand The value by which to multiply. 1252e5b6d6dSopenharmony_ci */ 1262e5b6d6dSopenharmony_ci void multiplyBy(const DecNum& multiplicand, UErrorCode& status); 1272e5b6d6dSopenharmony_ci 1282e5b6d6dSopenharmony_ci /** 1292e5b6d6dSopenharmony_ci * Divide the internal value. Uses decNumber. 1302e5b6d6dSopenharmony_ci * 1312e5b6d6dSopenharmony_ci * @param multiplicand The value by which to multiply. 1322e5b6d6dSopenharmony_ci */ 1332e5b6d6dSopenharmony_ci void divideBy(const DecNum& divisor, UErrorCode& status); 1342e5b6d6dSopenharmony_ci 1352e5b6d6dSopenharmony_ci /** Flips the sign from positive to negative and back. */ 1362e5b6d6dSopenharmony_ci void negate(); 1372e5b6d6dSopenharmony_ci 1382e5b6d6dSopenharmony_ci /** 1392e5b6d6dSopenharmony_ci * Scales the number by a power of ten. For example, if the value is currently "1234.56", calling 1402e5b6d6dSopenharmony_ci * this method with delta=-3 will change the value to "1.23456". 1412e5b6d6dSopenharmony_ci * 1422e5b6d6dSopenharmony_ci * @param delta The number of magnitudes of ten to change by. 1432e5b6d6dSopenharmony_ci * @return true if integer overflow occurred; false otherwise. 1442e5b6d6dSopenharmony_ci */ 1452e5b6d6dSopenharmony_ci bool adjustMagnitude(int32_t delta); 1462e5b6d6dSopenharmony_ci 1472e5b6d6dSopenharmony_ci /** 1482e5b6d6dSopenharmony_ci * Scales the number such that the least significant nonzero digit is at magnitude 0. 1492e5b6d6dSopenharmony_ci * 1502e5b6d6dSopenharmony_ci * @return The previous magnitude of the least significant digit. 1512e5b6d6dSopenharmony_ci */ 1522e5b6d6dSopenharmony_ci int32_t adjustToZeroScale(); 1532e5b6d6dSopenharmony_ci 1542e5b6d6dSopenharmony_ci /** 1552e5b6d6dSopenharmony_ci * @return The power of ten corresponding to the most significant nonzero digit. 1562e5b6d6dSopenharmony_ci * The number must not be zero. 1572e5b6d6dSopenharmony_ci */ 1582e5b6d6dSopenharmony_ci int32_t getMagnitude() const; 1592e5b6d6dSopenharmony_ci 1602e5b6d6dSopenharmony_ci /** 1612e5b6d6dSopenharmony_ci * @return The value of the (suppressed) exponent after the number has been 1622e5b6d6dSopenharmony_ci * put into a notation with exponents (ex: compact, scientific). Ex: given 1632e5b6d6dSopenharmony_ci * the number 1000 as "1K" / "1E3", the return value will be 3 (positive). 1642e5b6d6dSopenharmony_ci */ 1652e5b6d6dSopenharmony_ci int32_t getExponent() const; 1662e5b6d6dSopenharmony_ci 1672e5b6d6dSopenharmony_ci /** 1682e5b6d6dSopenharmony_ci * Adjusts the value for the (suppressed) exponent stored when using 1692e5b6d6dSopenharmony_ci * notation with exponents (ex: compact, scientific). 1702e5b6d6dSopenharmony_ci * 1712e5b6d6dSopenharmony_ci * <p>Adjusting the exponent is decoupled from {@link #adjustMagnitude} in 1722e5b6d6dSopenharmony_ci * order to allow flexibility for {@link StandardPlural} to be selected in 1732e5b6d6dSopenharmony_ci * formatting (ex: for compact notation) either with or without the exponent 1742e5b6d6dSopenharmony_ci * applied in the value of the number. 1752e5b6d6dSopenharmony_ci * @param delta 1762e5b6d6dSopenharmony_ci * The value to adjust the exponent by. 1772e5b6d6dSopenharmony_ci */ 1782e5b6d6dSopenharmony_ci void adjustExponent(int32_t delta); 1792e5b6d6dSopenharmony_ci 1802e5b6d6dSopenharmony_ci /** 1812e5b6d6dSopenharmony_ci * Resets the DecimalQuantity to the value before adjustMagnitude and adjustExponent. 1822e5b6d6dSopenharmony_ci */ 1832e5b6d6dSopenharmony_ci void resetExponent(); 1842e5b6d6dSopenharmony_ci 1852e5b6d6dSopenharmony_ci /** 1862e5b6d6dSopenharmony_ci * @return Whether the value represented by this {@link DecimalQuantity} is 1872e5b6d6dSopenharmony_ci * zero, infinity, or NaN. 1882e5b6d6dSopenharmony_ci */ 1892e5b6d6dSopenharmony_ci bool isZeroish() const; 1902e5b6d6dSopenharmony_ci 1912e5b6d6dSopenharmony_ci /** @return Whether the value represented by this {@link DecimalQuantity} is less than zero. */ 1922e5b6d6dSopenharmony_ci bool isNegative() const; 1932e5b6d6dSopenharmony_ci 1942e5b6d6dSopenharmony_ci /** @return The appropriate value from the Signum enum. */ 1952e5b6d6dSopenharmony_ci Signum signum() const; 1962e5b6d6dSopenharmony_ci 1972e5b6d6dSopenharmony_ci /** @return Whether the value represented by this {@link DecimalQuantity} is infinite. */ 1982e5b6d6dSopenharmony_ci bool isInfinite() const U_OVERRIDE; 1992e5b6d6dSopenharmony_ci 2002e5b6d6dSopenharmony_ci /** @return Whether the value represented by this {@link DecimalQuantity} is not a number. */ 2012e5b6d6dSopenharmony_ci bool isNaN() const U_OVERRIDE; 2022e5b6d6dSopenharmony_ci 2032e5b6d6dSopenharmony_ci /** 2042e5b6d6dSopenharmony_ci * Note: this method incorporates the value of {@code exponent} 2052e5b6d6dSopenharmony_ci * (for cases such as compact notation) to return the proper long value 2062e5b6d6dSopenharmony_ci * represented by the result. 2072e5b6d6dSopenharmony_ci * @param truncateIfOverflow if false and the number does NOT fit, fails with an assertion error. 2082e5b6d6dSopenharmony_ci */ 2092e5b6d6dSopenharmony_ci int64_t toLong(bool truncateIfOverflow = false) const; 2102e5b6d6dSopenharmony_ci 2112e5b6d6dSopenharmony_ci /** 2122e5b6d6dSopenharmony_ci * Note: this method incorporates the value of {@code exponent} 2132e5b6d6dSopenharmony_ci * (for cases such as compact notation) to return the proper long value 2142e5b6d6dSopenharmony_ci * represented by the result. 2152e5b6d6dSopenharmony_ci */ 2162e5b6d6dSopenharmony_ci uint64_t toFractionLong(bool includeTrailingZeros) const; 2172e5b6d6dSopenharmony_ci 2182e5b6d6dSopenharmony_ci /** 2192e5b6d6dSopenharmony_ci * Returns whether or not a Long can fully represent the value stored in this DecimalQuantity. 2202e5b6d6dSopenharmony_ci * @param ignoreFraction if true, silently ignore digits after the decimal place. 2212e5b6d6dSopenharmony_ci */ 2222e5b6d6dSopenharmony_ci bool fitsInLong(bool ignoreFraction = false) const; 2232e5b6d6dSopenharmony_ci 2242e5b6d6dSopenharmony_ci /** @return The value contained in this {@link DecimalQuantity} approximated as a double. */ 2252e5b6d6dSopenharmony_ci double toDouble() const; 2262e5b6d6dSopenharmony_ci 2272e5b6d6dSopenharmony_ci /** Computes a DecNum representation of this DecimalQuantity, saving it to the output parameter. */ 2282e5b6d6dSopenharmony_ci DecNum& toDecNum(DecNum& output, UErrorCode& status) const; 2292e5b6d6dSopenharmony_ci 2302e5b6d6dSopenharmony_ci DecimalQuantity &setToInt(int32_t n); 2312e5b6d6dSopenharmony_ci 2322e5b6d6dSopenharmony_ci DecimalQuantity &setToLong(int64_t n); 2332e5b6d6dSopenharmony_ci 2342e5b6d6dSopenharmony_ci DecimalQuantity &setToDouble(double n); 2352e5b6d6dSopenharmony_ci 2362e5b6d6dSopenharmony_ci /** 2372e5b6d6dSopenharmony_ci * Produces a DecimalQuantity that was parsed from a string by the decNumber 2382e5b6d6dSopenharmony_ci * C Library. 2392e5b6d6dSopenharmony_ci * 2402e5b6d6dSopenharmony_ci * decNumber is similar to BigDecimal in Java, and supports parsing strings 2412e5b6d6dSopenharmony_ci * such as "123.456621E+40". 2422e5b6d6dSopenharmony_ci */ 2432e5b6d6dSopenharmony_ci DecimalQuantity &setToDecNumber(StringPiece n, UErrorCode& status); 2442e5b6d6dSopenharmony_ci 2452e5b6d6dSopenharmony_ci /** Internal method if the caller already has a DecNum. */ 2462e5b6d6dSopenharmony_ci DecimalQuantity &setToDecNum(const DecNum& n, UErrorCode& status); 2472e5b6d6dSopenharmony_ci 2482e5b6d6dSopenharmony_ci /** Returns a DecimalQuantity after parsing the input string. */ 2492e5b6d6dSopenharmony_ci static DecimalQuantity fromExponentString(UnicodeString n, UErrorCode& status); 2502e5b6d6dSopenharmony_ci 2512e5b6d6dSopenharmony_ci /** 2522e5b6d6dSopenharmony_ci * Appends a digit, optionally with one or more leading zeros, to the end of the value represented 2532e5b6d6dSopenharmony_ci * by this DecimalQuantity. 2542e5b6d6dSopenharmony_ci * 2552e5b6d6dSopenharmony_ci * <p>The primary use of this method is to construct numbers during a parsing loop. It allows 2562e5b6d6dSopenharmony_ci * parsing to take advantage of the digit list infrastructure primarily designed for formatting. 2572e5b6d6dSopenharmony_ci * 2582e5b6d6dSopenharmony_ci * @param value The digit to append. 2592e5b6d6dSopenharmony_ci * @param leadingZeros The number of zeros to append before the digit. For example, if the value 2602e5b6d6dSopenharmony_ci * in this instance starts as 12.3, and you append a 4 with 1 leading zero, the value becomes 2612e5b6d6dSopenharmony_ci * 12.304. 2622e5b6d6dSopenharmony_ci * @param appendAsInteger If true, increase the magnitude of existing digits to make room for the 2632e5b6d6dSopenharmony_ci * new digit. If false, append to the end like a fraction digit. If true, there must not be 2642e5b6d6dSopenharmony_ci * any fraction digits already in the number. 2652e5b6d6dSopenharmony_ci * @internal 2662e5b6d6dSopenharmony_ci * @deprecated This API is ICU internal only. 2672e5b6d6dSopenharmony_ci */ 2682e5b6d6dSopenharmony_ci void appendDigit(int8_t value, int32_t leadingZeros, bool appendAsInteger); 2692e5b6d6dSopenharmony_ci 2702e5b6d6dSopenharmony_ci double getPluralOperand(PluralOperand operand) const U_OVERRIDE; 2712e5b6d6dSopenharmony_ci 2722e5b6d6dSopenharmony_ci bool hasIntegerValue() const U_OVERRIDE; 2732e5b6d6dSopenharmony_ci 2742e5b6d6dSopenharmony_ci /** 2752e5b6d6dSopenharmony_ci * Gets the digit at the specified magnitude. For example, if the represented number is 12.3, 2762e5b6d6dSopenharmony_ci * getDigit(-1) returns 3, since 3 is the digit corresponding to 10^-1. 2772e5b6d6dSopenharmony_ci * 2782e5b6d6dSopenharmony_ci * @param magnitude The magnitude of the digit. 2792e5b6d6dSopenharmony_ci * @return The digit at the specified magnitude. 2802e5b6d6dSopenharmony_ci */ 2812e5b6d6dSopenharmony_ci int8_t getDigit(int32_t magnitude) const; 2822e5b6d6dSopenharmony_ci 2832e5b6d6dSopenharmony_ci /** 2842e5b6d6dSopenharmony_ci * Gets the largest power of ten that needs to be displayed. The value returned by this function 2852e5b6d6dSopenharmony_ci * will be bounded between minInt and maxInt. 2862e5b6d6dSopenharmony_ci * 2872e5b6d6dSopenharmony_ci * @return The highest-magnitude digit to be displayed. 2882e5b6d6dSopenharmony_ci */ 2892e5b6d6dSopenharmony_ci int32_t getUpperDisplayMagnitude() const; 2902e5b6d6dSopenharmony_ci 2912e5b6d6dSopenharmony_ci /** 2922e5b6d6dSopenharmony_ci * Gets the smallest power of ten that needs to be displayed. The value returned by this function 2932e5b6d6dSopenharmony_ci * will be bounded between -minFrac and -maxFrac. 2942e5b6d6dSopenharmony_ci * 2952e5b6d6dSopenharmony_ci * @return The lowest-magnitude digit to be displayed. 2962e5b6d6dSopenharmony_ci */ 2972e5b6d6dSopenharmony_ci int32_t getLowerDisplayMagnitude() const; 2982e5b6d6dSopenharmony_ci 2992e5b6d6dSopenharmony_ci int32_t fractionCount() const; 3002e5b6d6dSopenharmony_ci 3012e5b6d6dSopenharmony_ci int32_t fractionCountWithoutTrailingZeros() const; 3022e5b6d6dSopenharmony_ci 3032e5b6d6dSopenharmony_ci void clear(); 3042e5b6d6dSopenharmony_ci 3052e5b6d6dSopenharmony_ci /** This method is for internal testing only. */ 3062e5b6d6dSopenharmony_ci uint64_t getPositionFingerprint() const; 3072e5b6d6dSopenharmony_ci 3082e5b6d6dSopenharmony_ci// /** 3092e5b6d6dSopenharmony_ci// * If the given {@link FieldPosition} is a {@link UFieldPosition}, populates it with the fraction 3102e5b6d6dSopenharmony_ci// * length and fraction long value. If the argument is not a {@link UFieldPosition}, nothing 3112e5b6d6dSopenharmony_ci// * happens. 3122e5b6d6dSopenharmony_ci// * 3132e5b6d6dSopenharmony_ci// * @param fp The {@link UFieldPosition} to populate. 3142e5b6d6dSopenharmony_ci// */ 3152e5b6d6dSopenharmony_ci// void populateUFieldPosition(FieldPosition fp); 3162e5b6d6dSopenharmony_ci 3172e5b6d6dSopenharmony_ci /** 3182e5b6d6dSopenharmony_ci * Checks whether the bytes stored in this instance are all valid. For internal unit testing only. 3192e5b6d6dSopenharmony_ci * 3202e5b6d6dSopenharmony_ci * @return An error message if this instance is invalid, or null if this instance is healthy. 3212e5b6d6dSopenharmony_ci */ 3222e5b6d6dSopenharmony_ci const char16_t* checkHealth() const; 3232e5b6d6dSopenharmony_ci 3242e5b6d6dSopenharmony_ci UnicodeString toString() const; 3252e5b6d6dSopenharmony_ci 3262e5b6d6dSopenharmony_ci /** Returns the string in standard exponential notation. */ 3272e5b6d6dSopenharmony_ci UnicodeString toScientificString() const; 3282e5b6d6dSopenharmony_ci 3292e5b6d6dSopenharmony_ci /** Returns the string without exponential notation. Slightly slower than toScientificString(). */ 3302e5b6d6dSopenharmony_ci UnicodeString toPlainString() const; 3312e5b6d6dSopenharmony_ci 3322e5b6d6dSopenharmony_ci /** Returns the string using ASCII digits and using exponential notation for non-zero 3332e5b6d6dSopenharmony_ci exponents, following the UTS 35 specification for plural rule samples. */ 3342e5b6d6dSopenharmony_ci UnicodeString toExponentString() const; 3352e5b6d6dSopenharmony_ci 3362e5b6d6dSopenharmony_ci /** Visible for testing */ 3372e5b6d6dSopenharmony_ci inline bool isUsingBytes() { return usingBytes; } 3382e5b6d6dSopenharmony_ci 3392e5b6d6dSopenharmony_ci /** Visible for testing */ 3402e5b6d6dSopenharmony_ci inline bool isExplicitExactDouble() { return explicitExactDouble; } 3412e5b6d6dSopenharmony_ci 3422e5b6d6dSopenharmony_ci bool operator==(const DecimalQuantity& other) const; 3432e5b6d6dSopenharmony_ci 3442e5b6d6dSopenharmony_ci inline bool operator!=(const DecimalQuantity& other) const { 3452e5b6d6dSopenharmony_ci return !(*this == other); 3462e5b6d6dSopenharmony_ci } 3472e5b6d6dSopenharmony_ci 3482e5b6d6dSopenharmony_ci /** 3492e5b6d6dSopenharmony_ci * Bogus flag for when a DecimalQuantity is stored on the stack. 3502e5b6d6dSopenharmony_ci */ 3512e5b6d6dSopenharmony_ci bool bogus = false; 3522e5b6d6dSopenharmony_ci 3532e5b6d6dSopenharmony_ci private: 3542e5b6d6dSopenharmony_ci /** 3552e5b6d6dSopenharmony_ci * The power of ten corresponding to the least significant digit in the BCD. For example, if this 3562e5b6d6dSopenharmony_ci * object represents the number "3.14", the BCD will be "0x314" and the scale will be -2. 3572e5b6d6dSopenharmony_ci * 3582e5b6d6dSopenharmony_ci * <p>Note that in {@link java.math.BigDecimal}, the scale is defined differently: the number of 3592e5b6d6dSopenharmony_ci * digits after the decimal place, which is the negative of our definition of scale. 3602e5b6d6dSopenharmony_ci */ 3612e5b6d6dSopenharmony_ci int32_t scale; 3622e5b6d6dSopenharmony_ci 3632e5b6d6dSopenharmony_ci /** 3642e5b6d6dSopenharmony_ci * The number of digits in the BCD. For example, "1007" has BCD "0x1007" and precision 4. The 3652e5b6d6dSopenharmony_ci * maximum precision is 16 since a long can hold only 16 digits. 3662e5b6d6dSopenharmony_ci * 3672e5b6d6dSopenharmony_ci * <p>This value must be re-calculated whenever the value in bcd changes by using {@link 3682e5b6d6dSopenharmony_ci * #computePrecisionAndCompact()}. 3692e5b6d6dSopenharmony_ci */ 3702e5b6d6dSopenharmony_ci int32_t precision; 3712e5b6d6dSopenharmony_ci 3722e5b6d6dSopenharmony_ci /** 3732e5b6d6dSopenharmony_ci * A bitmask of properties relating to the number represented by this object. 3742e5b6d6dSopenharmony_ci * 3752e5b6d6dSopenharmony_ci * @see #NEGATIVE_FLAG 3762e5b6d6dSopenharmony_ci * @see #INFINITY_FLAG 3772e5b6d6dSopenharmony_ci * @see #NAN_FLAG 3782e5b6d6dSopenharmony_ci */ 3792e5b6d6dSopenharmony_ci int8_t flags; 3802e5b6d6dSopenharmony_ci 3812e5b6d6dSopenharmony_ci // The following three fields relate to the double-to-ascii fast path algorithm. 3822e5b6d6dSopenharmony_ci // When a double is given to DecimalQuantityBCD, it is converted to using a fast algorithm. The 3832e5b6d6dSopenharmony_ci // fast algorithm guarantees correctness to only the first ~12 digits of the double. The process 3842e5b6d6dSopenharmony_ci // of rounding the number ensures that the converted digits are correct, falling back to a slow- 3852e5b6d6dSopenharmony_ci // path algorithm if required. Therefore, if a DecimalQuantity is constructed from a double, it 3862e5b6d6dSopenharmony_ci // is *required* that roundToMagnitude(), roundToIncrement(), or roundToInfinity() is called. If 3872e5b6d6dSopenharmony_ci // you don't round, assertions will fail in certain other methods if you try calling them. 3882e5b6d6dSopenharmony_ci 3892e5b6d6dSopenharmony_ci /** 3902e5b6d6dSopenharmony_ci * Whether the value in the BCD comes from the double fast path without having been rounded to 3912e5b6d6dSopenharmony_ci * ensure correctness 3922e5b6d6dSopenharmony_ci */ 3932e5b6d6dSopenharmony_ci UBool isApproximate; 3942e5b6d6dSopenharmony_ci 3952e5b6d6dSopenharmony_ci /** 3962e5b6d6dSopenharmony_ci * The original number provided by the user and which is represented in BCD. Used when we need to 3972e5b6d6dSopenharmony_ci * re-compute the BCD for an exact double representation. 3982e5b6d6dSopenharmony_ci */ 3992e5b6d6dSopenharmony_ci double origDouble; 4002e5b6d6dSopenharmony_ci 4012e5b6d6dSopenharmony_ci /** 4022e5b6d6dSopenharmony_ci * The change in magnitude relative to the original double. Used when we need to re-compute the 4032e5b6d6dSopenharmony_ci * BCD for an exact double representation. 4042e5b6d6dSopenharmony_ci */ 4052e5b6d6dSopenharmony_ci int32_t origDelta; 4062e5b6d6dSopenharmony_ci 4072e5b6d6dSopenharmony_ci // Positions to keep track of leading and trailing zeros. 4082e5b6d6dSopenharmony_ci // lReqPos is the magnitude of the first required leading zero. 4092e5b6d6dSopenharmony_ci // rReqPos is the magnitude of the last required trailing zero. 4102e5b6d6dSopenharmony_ci int32_t lReqPos = 0; 4112e5b6d6dSopenharmony_ci int32_t rReqPos = 0; 4122e5b6d6dSopenharmony_ci 4132e5b6d6dSopenharmony_ci // The value of the (suppressed) exponent after the number has been put into 4142e5b6d6dSopenharmony_ci // a notation with exponents (ex: compact, scientific). 4152e5b6d6dSopenharmony_ci int32_t exponent = 0; 4162e5b6d6dSopenharmony_ci 4172e5b6d6dSopenharmony_ci /** 4182e5b6d6dSopenharmony_ci * The BCD of the 16 digits of the number represented by this object. Every 4 bits of the long map 4192e5b6d6dSopenharmony_ci * to one digit. For example, the number "12345" in BCD is "0x12345". 4202e5b6d6dSopenharmony_ci * 4212e5b6d6dSopenharmony_ci * <p>Whenever bcd changes internally, {@link #compact()} must be called, except in special cases 4222e5b6d6dSopenharmony_ci * like setting the digit to zero. 4232e5b6d6dSopenharmony_ci */ 4242e5b6d6dSopenharmony_ci union { 4252e5b6d6dSopenharmony_ci struct { 4262e5b6d6dSopenharmony_ci int8_t *ptr; 4272e5b6d6dSopenharmony_ci int32_t len; 4282e5b6d6dSopenharmony_ci } bcdBytes; 4292e5b6d6dSopenharmony_ci uint64_t bcdLong; 4302e5b6d6dSopenharmony_ci } fBCD; 4312e5b6d6dSopenharmony_ci 4322e5b6d6dSopenharmony_ci bool usingBytes = false; 4332e5b6d6dSopenharmony_ci 4342e5b6d6dSopenharmony_ci /** 4352e5b6d6dSopenharmony_ci * Whether this {@link DecimalQuantity} has been explicitly converted to an exact double. true if 4362e5b6d6dSopenharmony_ci * backed by a double that was explicitly converted via convertToAccurateDouble; false otherwise. 4372e5b6d6dSopenharmony_ci * Used for testing. 4382e5b6d6dSopenharmony_ci */ 4392e5b6d6dSopenharmony_ci bool explicitExactDouble = false; 4402e5b6d6dSopenharmony_ci 4412e5b6d6dSopenharmony_ci void roundToMagnitude(int32_t magnitude, RoundingMode roundingMode, bool nickel, UErrorCode& status); 4422e5b6d6dSopenharmony_ci 4432e5b6d6dSopenharmony_ci /** 4442e5b6d6dSopenharmony_ci * Returns a single digit from the BCD list. No internal state is changed by calling this method. 4452e5b6d6dSopenharmony_ci * 4462e5b6d6dSopenharmony_ci * @param position The position of the digit to pop, counted in BCD units from the least 4472e5b6d6dSopenharmony_ci * significant digit. If outside the range supported by the implementation, zero is returned. 4482e5b6d6dSopenharmony_ci * @return The digit at the specified location. 4492e5b6d6dSopenharmony_ci */ 4502e5b6d6dSopenharmony_ci int8_t getDigitPos(int32_t position) const; 4512e5b6d6dSopenharmony_ci 4522e5b6d6dSopenharmony_ci /** 4532e5b6d6dSopenharmony_ci * Sets the digit in the BCD list. This method only sets the digit; it is the caller's 4542e5b6d6dSopenharmony_ci * responsibility to call {@link #compact} after setting the digit, and to ensure 4552e5b6d6dSopenharmony_ci * that the precision field is updated to reflect the correct number of digits if a 4562e5b6d6dSopenharmony_ci * nonzero digit is added to the decimal. 4572e5b6d6dSopenharmony_ci * 4582e5b6d6dSopenharmony_ci * @param position The position of the digit to pop, counted in BCD units from the least 4592e5b6d6dSopenharmony_ci * significant digit. If outside the range supported by the implementation, an AssertionError 4602e5b6d6dSopenharmony_ci * is thrown. 4612e5b6d6dSopenharmony_ci * @param value The digit to set at the specified location. 4622e5b6d6dSopenharmony_ci */ 4632e5b6d6dSopenharmony_ci void setDigitPos(int32_t position, int8_t value); 4642e5b6d6dSopenharmony_ci 4652e5b6d6dSopenharmony_ci /** 4662e5b6d6dSopenharmony_ci * Adds zeros to the end of the BCD list. This will result in an invalid BCD representation; it is 4672e5b6d6dSopenharmony_ci * the caller's responsibility to do further manipulation and then call {@link #compact}. 4682e5b6d6dSopenharmony_ci * 4692e5b6d6dSopenharmony_ci * @param numDigits The number of zeros to add. 4702e5b6d6dSopenharmony_ci */ 4712e5b6d6dSopenharmony_ci void shiftLeft(int32_t numDigits); 4722e5b6d6dSopenharmony_ci 4732e5b6d6dSopenharmony_ci /** 4742e5b6d6dSopenharmony_ci * Directly removes digits from the end of the BCD list. 4752e5b6d6dSopenharmony_ci * Updates the scale and precision. 4762e5b6d6dSopenharmony_ci * 4772e5b6d6dSopenharmony_ci * CAUTION: it is the caller's responsibility to call {@link #compact} after this method. 4782e5b6d6dSopenharmony_ci */ 4792e5b6d6dSopenharmony_ci void shiftRight(int32_t numDigits); 4802e5b6d6dSopenharmony_ci 4812e5b6d6dSopenharmony_ci /** 4822e5b6d6dSopenharmony_ci * Directly removes digits from the front of the BCD list. 4832e5b6d6dSopenharmony_ci * Updates precision. 4842e5b6d6dSopenharmony_ci * 4852e5b6d6dSopenharmony_ci * CAUTION: it is the caller's responsibility to call {@link #compact} after this method. 4862e5b6d6dSopenharmony_ci */ 4872e5b6d6dSopenharmony_ci void popFromLeft(int32_t numDigits); 4882e5b6d6dSopenharmony_ci 4892e5b6d6dSopenharmony_ci /** 4902e5b6d6dSopenharmony_ci * Sets the internal representation to zero. Clears any values stored in scale, precision, 4912e5b6d6dSopenharmony_ci * hasDouble, origDouble, origDelta, exponent, and BCD data. 4922e5b6d6dSopenharmony_ci */ 4932e5b6d6dSopenharmony_ci void setBcdToZero(); 4942e5b6d6dSopenharmony_ci 4952e5b6d6dSopenharmony_ci /** 4962e5b6d6dSopenharmony_ci * Sets the internal BCD state to represent the value in the given int. The int is guaranteed to 4972e5b6d6dSopenharmony_ci * be either positive. The internal state is guaranteed to be empty when this method is called. 4982e5b6d6dSopenharmony_ci * 4992e5b6d6dSopenharmony_ci * @param n The value to consume. 5002e5b6d6dSopenharmony_ci */ 5012e5b6d6dSopenharmony_ci void readIntToBcd(int32_t n); 5022e5b6d6dSopenharmony_ci 5032e5b6d6dSopenharmony_ci /** 5042e5b6d6dSopenharmony_ci * Sets the internal BCD state to represent the value in the given long. The long is guaranteed to 5052e5b6d6dSopenharmony_ci * be either positive. The internal state is guaranteed to be empty when this method is called. 5062e5b6d6dSopenharmony_ci * 5072e5b6d6dSopenharmony_ci * @param n The value to consume. 5082e5b6d6dSopenharmony_ci */ 5092e5b6d6dSopenharmony_ci void readLongToBcd(int64_t n); 5102e5b6d6dSopenharmony_ci 5112e5b6d6dSopenharmony_ci void readDecNumberToBcd(const DecNum& dn); 5122e5b6d6dSopenharmony_ci 5132e5b6d6dSopenharmony_ci void readDoubleConversionToBcd(const char* buffer, int32_t length, int32_t point); 5142e5b6d6dSopenharmony_ci 5152e5b6d6dSopenharmony_ci void copyFieldsFrom(const DecimalQuantity& other); 5162e5b6d6dSopenharmony_ci 5172e5b6d6dSopenharmony_ci void copyBcdFrom(const DecimalQuantity &other); 5182e5b6d6dSopenharmony_ci 5192e5b6d6dSopenharmony_ci void moveBcdFrom(DecimalQuantity& src); 5202e5b6d6dSopenharmony_ci 5212e5b6d6dSopenharmony_ci /** 5222e5b6d6dSopenharmony_ci * Removes trailing zeros from the BCD (adjusting the scale as required) and then computes the 5232e5b6d6dSopenharmony_ci * precision. The precision is the number of digits in the number up through the greatest nonzero 5242e5b6d6dSopenharmony_ci * digit. 5252e5b6d6dSopenharmony_ci * 5262e5b6d6dSopenharmony_ci * <p>This method must always be called when bcd changes in order for assumptions to be correct in 5272e5b6d6dSopenharmony_ci * methods like {@link #fractionCount()}. 5282e5b6d6dSopenharmony_ci */ 5292e5b6d6dSopenharmony_ci void compact(); 5302e5b6d6dSopenharmony_ci 5312e5b6d6dSopenharmony_ci void _setToInt(int32_t n); 5322e5b6d6dSopenharmony_ci 5332e5b6d6dSopenharmony_ci void _setToLong(int64_t n); 5342e5b6d6dSopenharmony_ci 5352e5b6d6dSopenharmony_ci void _setToDoubleFast(double n); 5362e5b6d6dSopenharmony_ci 5372e5b6d6dSopenharmony_ci void _setToDecNum(const DecNum& dn, UErrorCode& status); 5382e5b6d6dSopenharmony_ci 5392e5b6d6dSopenharmony_ci static int32_t getVisibleFractionCount(UnicodeString value); 5402e5b6d6dSopenharmony_ci 5412e5b6d6dSopenharmony_ci void convertToAccurateDouble(); 5422e5b6d6dSopenharmony_ci 5432e5b6d6dSopenharmony_ci /** Ensure that a byte array of at least 40 digits is allocated. */ 5442e5b6d6dSopenharmony_ci void ensureCapacity(); 5452e5b6d6dSopenharmony_ci 5462e5b6d6dSopenharmony_ci void ensureCapacity(int32_t capacity); 5472e5b6d6dSopenharmony_ci 5482e5b6d6dSopenharmony_ci /** Switches the internal storage mechanism between the 64-bit long and the byte array. */ 5492e5b6d6dSopenharmony_ci void switchStorage(); 5502e5b6d6dSopenharmony_ci}; 5512e5b6d6dSopenharmony_ci 5522e5b6d6dSopenharmony_ci} // namespace impl 5532e5b6d6dSopenharmony_ci} // namespace number 5542e5b6d6dSopenharmony_ciU_NAMESPACE_END 5552e5b6d6dSopenharmony_ci 5562e5b6d6dSopenharmony_ci 5572e5b6d6dSopenharmony_ci#endif //__NUMBER_DECIMALQUANTITY_H__ 5582e5b6d6dSopenharmony_ci 5592e5b6d6dSopenharmony_ci#endif /* #if !UCONFIG_NO_FORMATTING */ 560