Coverage Report

Created: 2018-09-25 14:53

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