Coverage Report

Created: 2023-02-22 06:51

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