tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

number_decimalquantity.h (20547B)


      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
      7 #ifndef __NUMBER_DECIMALQUANTITY_H__
      8 #define __NUMBER_DECIMALQUANTITY_H__
      9 
     10 #include <cstdint>
     11 #include "unicode/umachine.h"
     12 #include "standardplural.h"
     13 #include "plurrule_impl.h"
     14 #include "number_types.h"
     15 
     16 U_NAMESPACE_BEGIN
     17 namespace number::impl {
     18 
     19 // Forward-declare (maybe don't want number_utils.h included here):
     20 class DecNum;
     21 
     22 /**
     23 * A class for representing a number to be processed by the decimal formatting pipeline. Includes
     24 * methods for rounding, plural rules, and decimal digit extraction.
     25 *
     26 * <p>By design, this is NOT IMMUTABLE and NOT THREAD SAFE. It is intended to be an intermediate
     27 * object holding state during a pass through the decimal formatting pipeline.
     28 *
     29 * <p>Represents numbers and digit display properties using Binary Coded Decimal (BCD).
     30 *
     31 * <p>Java has multiple implementations for testing, but C++ has only one implementation.
     32 */
     33 class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory {
     34  public:
     35    /** Copy constructor. */
     36    DecimalQuantity(const DecimalQuantity &other);
     37 
     38    /** Move constructor. */
     39    DecimalQuantity(DecimalQuantity &&src) noexcept;
     40 
     41    DecimalQuantity();
     42 
     43    ~DecimalQuantity() override;
     44 
     45    /**
     46     * Sets this instance to be equal to another instance.
     47     *
     48     * @param other The instance to copy from.
     49     */
     50    DecimalQuantity &operator=(const DecimalQuantity &other);
     51 
     52    /** Move assignment */
     53    DecimalQuantity &operator=(DecimalQuantity&& src) noexcept;
     54 
     55    /**
     56     * If the minimum integer digits are greater than `minInt`,
     57     * sets it to `minInt`.
     58     *
     59     * @param minInt The minimum number of integer digits.
     60     */
     61    void decreaseMinIntegerTo(int32_t minInt);
     62 
     63    /**
     64     * Sets the minimum integer digits that this {@link DecimalQuantity} should generate.
     65     * This method does not perform rounding.
     66     *
     67     * @param minInt The minimum number of integer digits.
     68     */
     69    void increaseMinIntegerTo(int32_t minInt);
     70 
     71    /**
     72     * Sets the minimum fraction digits that this {@link DecimalQuantity} should generate.
     73     * This method does not perform rounding.
     74     *
     75     * @param minFrac The minimum number of fraction digits.
     76     */
     77    void setMinFraction(int32_t minFrac);
     78 
     79    /**
     80     * Truncates digits from the upper magnitude of the number in order to satisfy the
     81     * specified maximum number of integer digits.
     82     *
     83     * @param maxInt The maximum number of integer digits.
     84     */
     85    void applyMaxInteger(int32_t maxInt);
     86 
     87    /**
     88     * Rounds the number to a specified interval, such as 0.05.
     89     *
     90     * <p>If rounding to a power of ten, use the more efficient {@link #roundToMagnitude} instead.
     91     *
     92     * @param increment The increment to which to round.
     93     * @param magnitude The power of 10 to which to round.
     94     * @param roundingMode The {@link RoundingMode} to use if rounding is necessary.
     95     */
     96    void roundToIncrement(
     97        uint64_t increment,
     98        digits_t magnitude,
     99        RoundingMode roundingMode,
    100        UErrorCode& status);
    101 
    102    /** Removes all fraction digits. */
    103    void truncate();
    104 
    105    /**
    106     * Rounds the number to the nearest multiple of 5 at the specified magnitude.
    107     * For example, when magnitude == -2, this performs rounding to the nearest 0.05.
    108     *
    109     * @param magnitude The magnitude at which the digit should become either 0 or 5.
    110     * @param roundingMode Rounding strategy.
    111     */
    112    void roundToNickel(int32_t magnitude, RoundingMode roundingMode, UErrorCode& status);
    113 
    114    /**
    115     * Rounds the number to a specified magnitude (power of ten).
    116     *
    117     * @param roundingMagnitude The power of ten to which to round. For example, a value of -2 will
    118     *     round to 2 decimal places.
    119     * @param roundingMode The {@link RoundingMode} to use if rounding is necessary.
    120     */
    121    void roundToMagnitude(int32_t magnitude, RoundingMode roundingMode, UErrorCode& status);
    122 
    123    /**
    124     * Rounds the number to an infinite number of decimal points. This has no effect except for
    125     * forcing the double in {@link DecimalQuantity_AbstractBCD} to adopt its exact representation.
    126     */
    127    void roundToInfinity();
    128 
    129    /**
    130     * Multiply the internal value. Uses decNumber.
    131     *
    132     * @param multiplicand The value by which to multiply.
    133     */
    134    void multiplyBy(const DecNum& multiplicand, UErrorCode& status);
    135 
    136    /**
    137     * Divide the internal value. Uses decNumber.
    138     *
    139     * @param multiplicand The value by which to multiply.
    140     */
    141    void divideBy(const DecNum& divisor, UErrorCode& status);
    142 
    143    /** Flips the sign from positive to negative and back. */
    144    void negate();
    145 
    146    /**
    147     * Scales the number by a power of ten. For example, if the value is currently "1234.56", calling
    148     * this method with delta=-3 will change the value to "1.23456".
    149     *
    150     * @param delta The number of magnitudes of ten to change by.
    151     * @return true if integer overflow occurred; false otherwise.
    152     */
    153    bool adjustMagnitude(int32_t delta);
    154 
    155    /**
    156     * Scales the number such that the least significant nonzero digit is at magnitude 0.
    157     *
    158     * @return The previous magnitude of the least significant digit.
    159     */
    160    int32_t adjustToZeroScale();
    161 
    162    /**
    163     * @return The power of ten corresponding to the most significant nonzero digit.
    164     * The number must not be zero.
    165     */
    166    int32_t getMagnitude() const;
    167 
    168    /**
    169     * @return The value of the (suppressed) exponent after the number has been
    170     * put into a notation with exponents (ex: compact, scientific).  Ex: given
    171     * the number 1000 as "1K" / "1E3", the return value will be 3 (positive).
    172     */
    173    int32_t getExponent() const;
    174 
    175    /**
    176     * Adjusts the value for the (suppressed) exponent stored when using
    177     * notation with exponents (ex: compact, scientific).
    178     *
    179     * <p>Adjusting the exponent is decoupled from {@link #adjustMagnitude} in
    180     * order to allow flexibility for {@link StandardPlural} to be selected in
    181     * formatting (ex: for compact notation) either with or without the exponent
    182     * applied in the value of the number.
    183     * @param delta
    184     *             The value to adjust the exponent by.
    185     */
    186    void adjustExponent(int32_t delta);
    187 
    188    /**
    189     * Resets the DecimalQuantity to the value before adjustMagnitude and adjustExponent.
    190     */
    191    void resetExponent();
    192 
    193    /**
    194     * @return Whether the value represented by this {@link DecimalQuantity} is
    195     * zero, infinity, or NaN.
    196     */
    197    bool isZeroish() const;
    198 
    199    /** @return Whether the value represented by this {@link DecimalQuantity} is less than zero. */
    200    bool isNegative() const;
    201 
    202    /** @return The appropriate value from the Signum enum. */
    203    Signum signum() const;
    204 
    205    /** @return Whether the value represented by this {@link DecimalQuantity} is infinite. */
    206    bool isInfinite() const override;
    207 
    208    /** @return Whether the value represented by this {@link DecimalQuantity} is not a number. */
    209    bool isNaN() const override;
    210 
    211    /**  
    212     * Note: this method incorporates the value of {@code exponent}
    213     * (for cases such as compact notation) to return the proper long value
    214     * represented by the result.
    215     * @param truncateIfOverflow if false and the number does NOT fit, fails with an assertion error. 
    216     */
    217    int64_t toLong(bool truncateIfOverflow = false) const;
    218 
    219    /**
    220     * Note: this method incorporates the value of {@code exponent}
    221     * (for cases such as compact notation) to return the proper long value
    222     * represented by the result.
    223     */
    224    uint64_t toFractionLong(bool includeTrailingZeros) const;
    225 
    226    /**
    227     * Returns whether or not a Long can fully represent the value stored in this DecimalQuantity.
    228     * @param ignoreFraction if true, silently ignore digits after the decimal place.
    229     */
    230    bool fitsInLong(bool ignoreFraction = false) const;
    231 
    232    /** @return The value contained in this {@link DecimalQuantity} approximated as a double. */
    233    double toDouble() const;
    234 
    235    /** Computes a DecNum representation of this DecimalQuantity, saving it to the output parameter. */
    236    DecNum& toDecNum(DecNum& output, UErrorCode& status) const;
    237 
    238    DecimalQuantity &setToInt(int32_t n);
    239 
    240    DecimalQuantity &setToLong(int64_t n);
    241 
    242    DecimalQuantity &setToDouble(double n);
    243 
    244    /**
    245     * Produces a DecimalQuantity that was parsed from a string by the decNumber
    246     * C Library.
    247     *
    248     * decNumber is similar to BigDecimal in Java, and supports parsing strings
    249     * such as "123.456621E+40".
    250     */
    251    DecimalQuantity &setToDecNumber(StringPiece n, UErrorCode& status);
    252 
    253    /** Internal method if the caller already has a DecNum. */
    254    DecimalQuantity &setToDecNum(const DecNum& n, UErrorCode& status);
    255 
    256    /** Returns a DecimalQuantity after parsing the input string. */
    257    static DecimalQuantity fromExponentString(UnicodeString n, UErrorCode& status);
    258 
    259    /**
    260     * Appends a digit, optionally with one or more leading zeros, to the end of the value represented
    261     * by this DecimalQuantity.
    262     *
    263     * <p>The primary use of this method is to construct numbers during a parsing loop. It allows
    264     * parsing to take advantage of the digit list infrastructure primarily designed for formatting.
    265     *
    266     * @param value The digit to append.
    267     * @param leadingZeros The number of zeros to append before the digit. For example, if the value
    268     *     in this instance starts as 12.3, and you append a 4 with 1 leading zero, the value becomes
    269     *     12.304.
    270     * @param appendAsInteger If true, increase the magnitude of existing digits to make room for the
    271     *     new digit. If false, append to the end like a fraction digit. If true, there must not be
    272     *     any fraction digits already in the number.
    273     * @internal
    274     * @deprecated This API is ICU internal only.
    275     */
    276    void appendDigit(int8_t value, int32_t leadingZeros, bool appendAsInteger);
    277 
    278    double getPluralOperand(PluralOperand operand) const override;
    279 
    280    bool hasIntegerValue() const override;
    281 
    282    /**
    283     * Gets the digit at the specified magnitude. For example, if the represented number is 12.3,
    284     * getDigit(-1) returns 3, since 3 is the digit corresponding to 10^-1.
    285     *
    286     * @param magnitude The magnitude of the digit.
    287     * @return The digit at the specified magnitude.
    288     */
    289    int8_t getDigit(int32_t magnitude) const;
    290 
    291    /**
    292     * Gets the largest power of ten that needs to be displayed. The value returned by this function
    293     * will be bounded between minInt and maxInt.
    294     *
    295     * @return The highest-magnitude digit to be displayed.
    296     */
    297    int32_t getUpperDisplayMagnitude() const;
    298 
    299    /**
    300     * Gets the smallest power of ten that needs to be displayed. The value returned by this function
    301     * will be bounded between -minFrac and -maxFrac.
    302     *
    303     * @return The lowest-magnitude digit to be displayed.
    304     */
    305    int32_t getLowerDisplayMagnitude() const;
    306 
    307    int32_t fractionCount() const;
    308 
    309    int32_t fractionCountWithoutTrailingZeros() const;
    310 
    311    void clear();
    312 
    313    /** This method is for internal testing only. */
    314    uint64_t getPositionFingerprint() const;
    315 
    316 //    /**
    317 //     * If the given {@link FieldPosition} is a {@link UFieldPosition}, populates it with the fraction
    318 //     * length and fraction long value. If the argument is not a {@link UFieldPosition}, nothing
    319 //     * happens.
    320 //     *
    321 //     * @param fp The {@link UFieldPosition} to populate.
    322 //     */
    323 //    void populateUFieldPosition(FieldPosition fp);
    324 
    325    /**
    326     * Checks whether the bytes stored in this instance are all valid. For internal unit testing only.
    327     *
    328     * @return An error message if this instance is invalid, or null if this instance is healthy.
    329     */
    330    const char16_t* checkHealth() const;
    331 
    332    UnicodeString toString() const;
    333 
    334    /** Returns the string in standard exponential notation. */
    335    UnicodeString toScientificString() const;
    336 
    337    /** Returns the string without exponential notation. Slightly slower than toScientificString(). */
    338    UnicodeString toPlainString() const;
    339 
    340    /** Returns the string using ASCII digits and using exponential notation for non-zero
    341    exponents, following the UTS 35 specification for plural rule samples. */
    342    UnicodeString toExponentString() const;
    343 
    344    /** Visible for testing */
    345    inline bool isUsingBytes() { return usingBytes; }
    346 
    347    /** Visible for testing */
    348    inline bool isExplicitExactDouble() { return explicitExactDouble; }
    349 
    350    bool operator==(const DecimalQuantity& other) const;
    351 
    352    inline bool operator!=(const DecimalQuantity& other) const {
    353        return !(*this == other);
    354    }
    355 
    356    /**
    357     * Bogus flag for when a DecimalQuantity is stored on the stack.
    358     */
    359    bool bogus = false;
    360 
    361  private:
    362    /**
    363     * The power of ten corresponding to the least significant digit in the BCD. For example, if this
    364     * object represents the number "3.14", the BCD will be "0x314" and the scale will be -2.
    365     *
    366     * <p>Note that in {@link java.math.BigDecimal}, the scale is defined differently: the number of
    367     * digits after the decimal place, which is the negative of our definition of scale.
    368     */
    369    int32_t scale;
    370 
    371    /**
    372     * The number of digits in the BCD. For example, "1007" has BCD "0x1007" and precision 4. The
    373     * maximum precision is 16 since a long can hold only 16 digits.
    374     *
    375     * <p>This value must be re-calculated whenever the value in bcd changes by using {@link
    376     * #computePrecisionAndCompact()}.
    377     */
    378    int32_t precision;
    379 
    380    /**
    381     * A bitmask of properties relating to the number represented by this object.
    382     *
    383     * @see #NEGATIVE_FLAG
    384     * @see #INFINITY_FLAG
    385     * @see #NAN_FLAG
    386     */
    387    int8_t flags;
    388 
    389    // The following three fields relate to the double-to-ascii fast path algorithm.
    390    // When a double is given to DecimalQuantityBCD, it is converted to using a fast algorithm. The
    391    // fast algorithm guarantees correctness to only the first ~12 digits of the double. The process
    392    // of rounding the number ensures that the converted digits are correct, falling back to a slow-
    393    // path algorithm if required.  Therefore, if a DecimalQuantity is constructed from a double, it
    394    // is *required* that roundToMagnitude(), roundToIncrement(), or roundToInfinity() is called. If
    395    // you don't round, assertions will fail in certain other methods if you try calling them.
    396 
    397    /**
    398     * Whether the value in the BCD comes from the double fast path without having been rounded to
    399     * ensure correctness
    400     */
    401    UBool isApproximate;
    402 
    403    /**
    404     * The original number provided by the user and which is represented in BCD. Used when we need to
    405     * re-compute the BCD for an exact double representation.
    406     */
    407    double origDouble;
    408 
    409    /**
    410     * The change in magnitude relative to the original double. Used when we need to re-compute the
    411     * BCD for an exact double representation.
    412     */
    413    int32_t origDelta;
    414 
    415    // Positions to keep track of leading and trailing zeros.
    416    // lReqPos is the magnitude of the first required leading zero.
    417    // rReqPos is the magnitude of the last required trailing zero.
    418    int32_t lReqPos = 0;
    419    int32_t rReqPos = 0;
    420 
    421    // The value of the (suppressed) exponent after the number has been put into
    422    // a notation with exponents (ex: compact, scientific).
    423    int32_t exponent = 0;
    424 
    425    /**
    426     * The BCD of the 16 digits of the number represented by this object. Every 4 bits of the long map
    427     * to one digit. For example, the number "12345" in BCD is "0x12345".
    428     *
    429     * <p>Whenever bcd changes internally, {@link #compact()} must be called, except in special cases
    430     * like setting the digit to zero.
    431     */
    432    union {
    433        struct {
    434            int8_t *ptr;
    435            int32_t len;
    436        } bcdBytes;
    437        uint64_t bcdLong;
    438    } fBCD;
    439 
    440    bool usingBytes = false;
    441 
    442    /**
    443     * Whether this {@link DecimalQuantity} has been explicitly converted to an exact double. true if
    444     * backed by a double that was explicitly converted via convertToAccurateDouble; false otherwise.
    445     * Used for testing.
    446     */
    447    bool explicitExactDouble = false;
    448 
    449    void roundToMagnitude(int32_t magnitude, RoundingMode roundingMode, bool nickel, UErrorCode& status);
    450 
    451    /**
    452     * Returns a single digit from the BCD list. No internal state is changed by calling this method.
    453     *
    454     * @param position The position of the digit to pop, counted in BCD units from the least
    455     *     significant digit. If outside the range supported by the implementation, zero is returned.
    456     * @return The digit at the specified location.
    457     */
    458    int8_t getDigitPos(int32_t position) const;
    459 
    460    /**
    461     * Sets the digit in the BCD list. This method only sets the digit; it is the caller's
    462     * responsibility to call {@link #compact} after setting the digit, and to ensure
    463     * that the precision field is updated to reflect the correct number of digits if a
    464     * nonzero digit is added to the decimal.
    465     *
    466     * @param position The position of the digit to pop, counted in BCD units from the least
    467     *     significant digit. If outside the range supported by the implementation, an AssertionError
    468     *     is thrown.
    469     * @param value The digit to set at the specified location.
    470     */
    471    void setDigitPos(int32_t position, int8_t value);
    472 
    473    /**
    474     * Adds zeros to the end of the BCD list. This will result in an invalid BCD representation; it is
    475     * the caller's responsibility to do further manipulation and then call {@link #compact}.
    476     *
    477     * @param numDigits The number of zeros to add.
    478     */
    479    void shiftLeft(int32_t numDigits);
    480 
    481    /**
    482     * Directly removes digits from the end of the BCD list.
    483     * Updates the scale and precision.
    484     *
    485     * CAUTION: it is the caller's responsibility to call {@link #compact} after this method.
    486     */
    487    void shiftRight(int32_t numDigits);
    488 
    489    /**
    490     * Directly removes digits from the front of the BCD list.
    491     * Updates precision.
    492     *
    493     * CAUTION: it is the caller's responsibility to call {@link #compact} after this method.
    494     */
    495    void popFromLeft(int32_t numDigits);
    496 
    497    /**
    498     * Sets the internal representation to zero. Clears any values stored in scale, precision,
    499     * hasDouble, origDouble, origDelta, exponent, and BCD data.
    500     */
    501    void setBcdToZero();
    502 
    503    /**
    504     * Sets the internal BCD state to represent the value in the given int. The int is guaranteed to
    505     * be either positive. The internal state is guaranteed to be empty when this method is called.
    506     *
    507     * @param n The value to consume.
    508     */
    509    void readIntToBcd(int32_t n);
    510 
    511    /**
    512     * Sets the internal BCD state to represent the value in the given long. The long is guaranteed to
    513     * be either positive. The internal state is guaranteed to be empty when this method is called.
    514     *
    515     * @param n The value to consume.
    516     */
    517    void readLongToBcd(int64_t n);
    518 
    519    void readDecNumberToBcd(const DecNum& dn);
    520 
    521    void readDoubleConversionToBcd(const char* buffer, int32_t length, int32_t point);
    522 
    523    void copyFieldsFrom(const DecimalQuantity& other);
    524 
    525    void copyBcdFrom(const DecimalQuantity &other);
    526 
    527    void moveBcdFrom(DecimalQuantity& src);
    528 
    529    /**
    530     * Removes trailing zeros from the BCD (adjusting the scale as required) and then computes the
    531     * precision. The precision is the number of digits in the number up through the greatest nonzero
    532     * digit.
    533     *
    534     * <p>This method must always be called when bcd changes in order for assumptions to be correct in
    535     * methods like {@link #fractionCount()}.
    536     */
    537    void compact();
    538 
    539    void _setToInt(int32_t n);
    540 
    541    void _setToLong(int64_t n);
    542 
    543    void _setToDoubleFast(double n);
    544 
    545    void _setToDecNum(const DecNum& dn, UErrorCode& status);
    546 
    547    static int32_t getVisibleFractionCount(UnicodeString value);
    548 
    549    void convertToAccurateDouble();
    550 
    551    /** Ensure that a byte array of at least 40 digits is allocated. */
    552    void ensureCapacity();
    553 
    554    void ensureCapacity(int32_t capacity);
    555 
    556    /** Switches the internal storage mechanism between the 64-bit long and the byte array. */
    557    void switchStorage();
    558 };
    559 
    560 } // namespace number::impl
    561 U_NAMESPACE_END
    562 
    563 
    564 #endif //__NUMBER_DECIMALQUANTITY_H__
    565 
    566 #endif /* #if !UCONFIG_NO_FORMATTING */