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 */ isUsingBytes()345 inline bool isUsingBytes() { return usingBytes; } 346 347 /** Visible for testing */ isExplicitExactDouble()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 */ 567