Coverage Report

Created: 2026-01-22 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/icu/icu4c/source/i18n/number_decimalquantity.cpp
Line
Count
Source
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
8
#include <cstdlib>
9
#include <cmath>
10
#include <limits>
11
#include <stdlib.h>
12
13
#include "unicode/plurrule.h"
14
#include "cmemory.h"
15
#include "number_decnum.h"
16
#include "putilimp.h"
17
#include "number_decimalquantity.h"
18
#include "number_roundingutils.h"
19
#include "double-conversion.h"
20
#include "charstr.h"
21
#include "number_utils.h"
22
#include "uassert.h"
23
#include "util.h"
24
25
using namespace icu;
26
using namespace icu::number;
27
using namespace icu::number::impl;
28
29
using icu::double_conversion::DoubleToStringConverter;
30
using icu::double_conversion::StringToDoubleConverter;
31
32
namespace {
33
34
int8_t NEGATIVE_FLAG = 1;
35
int8_t INFINITY_FLAG = 2;
36
int8_t NAN_FLAG = 4;
37
38
/** Helper function for safe subtraction (no overflow). */
39
4.78M
inline int32_t safeSubtract(int32_t a, int32_t b) {
40
    // Note: In C++, signed integer subtraction is undefined behavior.
41
4.78M
    int32_t diff = static_cast<int32_t>(static_cast<uint32_t>(a) - static_cast<uint32_t>(b));
42
4.78M
    if (b < 0 && diff < a) { return INT32_MAX; }
43
4.78M
    if (b > 0 && diff > a) { return INT32_MIN; }
44
4.78M
    return diff;
45
4.78M
}
46
47
double DOUBLE_MULTIPLIERS[] = {
48
        1e0,
49
        1e1,
50
        1e2,
51
        1e3,
52
        1e4,
53
        1e5,
54
        1e6,
55
        1e7,
56
        1e8,
57
        1e9,
58
        1e10,
59
        1e11,
60
        1e12,
61
        1e13,
62
        1e14,
63
        1e15,
64
        1e16,
65
        1e17,
66
        1e18,
67
        1e19,
68
        1e20,
69
        1e21};
70
71
}  // namespace
72
73
12.9M
icu::IFixedDecimal::~IFixedDecimal() = default;
74
75
10.4M
DecimalQuantity::DecimalQuantity() {
76
10.4M
    setBcdToZero();
77
10.4M
    flags = 0;
78
10.4M
}
79
80
12.9M
DecimalQuantity::~DecimalQuantity() {
81
12.9M
    if (usingBytes) {
82
179k
        uprv_free(fBCD.bcdBytes.ptr);
83
179k
        fBCD.bcdBytes.ptr = nullptr;
84
179k
        usingBytes = false;
85
179k
    }
86
12.9M
}
87
88
2.51M
DecimalQuantity::DecimalQuantity(const DecimalQuantity &other) {
89
2.51M
    *this = other;
90
2.51M
}
91
92
0
DecimalQuantity::DecimalQuantity(DecimalQuantity&& src) noexcept {
93
0
    *this = std::move(src);
94
0
}
95
96
4.38M
DecimalQuantity &DecimalQuantity::operator=(const DecimalQuantity &other) {
97
4.38M
    if (this == &other) {
98
0
        return *this;
99
0
    }
100
4.38M
    copyBcdFrom(other);
101
4.38M
    copyFieldsFrom(other);
102
4.38M
    return *this;
103
4.38M
}
104
105
0
DecimalQuantity& DecimalQuantity::operator=(DecimalQuantity&& src) noexcept {
106
0
    if (this == &src) {
107
0
        return *this;
108
0
    }
109
0
    moveBcdFrom(src);
110
0
    copyFieldsFrom(src);
111
0
    return *this;
112
0
}
113
114
4.38M
void DecimalQuantity::copyFieldsFrom(const DecimalQuantity& other) {
115
4.38M
    bogus = other.bogus;
116
4.38M
    lReqPos = other.lReqPos;
117
4.38M
    rReqPos = other.rReqPos;
118
4.38M
    scale = other.scale;
119
4.38M
    precision = other.precision;
120
4.38M
    flags = other.flags;
121
4.38M
    origDouble = other.origDouble;
122
4.38M
    origDelta = other.origDelta;
123
4.38M
    isApproximate = other.isApproximate;
124
4.38M
    exponent = other.exponent;
125
4.38M
}
126
127
1.48M
void DecimalQuantity::clear() {
128
1.48M
    lReqPos = 0;
129
1.48M
    rReqPos = 0;
130
1.48M
    flags = 0;
131
1.48M
    setBcdToZero(); // sets scale, precision, hasDouble, origDouble, origDelta, and BCD data
132
1.48M
}
133
134
187k
void DecimalQuantity::decreaseMinIntegerTo(int32_t minInt) {
135
    // Validation should happen outside of DecimalQuantity, e.g., in the Precision class.
136
187k
    U_ASSERT(minInt >= 0);
137
138
187k
    if (lReqPos > minInt) {
139
565
        lReqPos = minInt;
140
565
    }
141
187k
}
142
143
2.37M
void DecimalQuantity::increaseMinIntegerTo(int32_t minInt) {
144
    // Validation should happen outside of DecimalQuantity, e.g., in the Precision class.
145
2.37M
    U_ASSERT(minInt >= 0);
146
147
    // Special behavior: do not set minInt to be less than what is already set.
148
    // This is so significant digits rounding can set the integer length.
149
2.37M
    if (lReqPos < minInt) {
150
2.37M
        lReqPos = minInt;
151
2.37M
    }
152
2.37M
}
153
154
2.28M
void DecimalQuantity::setMinFraction(int32_t minFrac) {
155
    // Validation should happen outside of DecimalQuantity, e.g., in the Precision class.
156
2.28M
    U_ASSERT(minFrac >= 0);
157
158
    // Save values into internal state
159
    // Negation is safe for minFrac/maxFrac because -Integer.MAX_VALUE > Integer.MIN_VALUE
160
2.28M
    rReqPos = -minFrac;
161
2.28M
}
162
163
93.9k
void DecimalQuantity::applyMaxInteger(int32_t maxInt) {
164
    // Validation should happen outside of DecimalQuantity, e.g., in the Precision class.
165
93.9k
    U_ASSERT(maxInt >= 0);
166
167
93.9k
    if (precision == 0) {
168
21.3k
        return;
169
21.3k
    }
170
171
72.6k
    if (maxInt <= scale) {
172
12
        setBcdToZero();
173
12
        return;
174
12
    }
175
176
72.6k
    int32_t magnitude = getMagnitude();
177
72.6k
    if (maxInt <= magnitude) {
178
1.08k
        popFromLeft(magnitude - maxInt + 1);
179
1.08k
        compact();
180
1.08k
    }
181
72.6k
}
182
183
0
uint64_t DecimalQuantity::getPositionFingerprint() const {
184
0
    uint64_t fingerprint = 0;
185
0
    fingerprint ^= (lReqPos << 16);
186
0
    fingerprint ^= (static_cast<uint64_t>(rReqPos) << 32);
187
0
    return fingerprint;
188
0
}
189
190
void DecimalQuantity::roundToIncrement(
191
        uint64_t increment,
192
        digits_t magnitude,
193
        RoundingMode roundingMode,
194
0
        UErrorCode& status) {
195
    // Do not call this method with an increment having only a 1 or a 5 digit!
196
    // Use a more efficient call to either roundToMagnitude() or roundToNickel().
197
    // Check a few popular rounding increments; a more thorough check is in Java.
198
0
    U_ASSERT(increment != 1);
199
0
    U_ASSERT(increment != 5);
200
201
0
    DecimalQuantity incrementDQ;
202
0
    incrementDQ.setToLong(increment);
203
0
    incrementDQ.adjustMagnitude(magnitude);
204
0
    DecNum incrementDN;
205
0
    incrementDQ.toDecNum(incrementDN, status);
206
0
    if (U_FAILURE(status)) { return; }
207
208
    // Divide this DecimalQuantity by the increment, round, then multiply back.
209
0
    divideBy(incrementDN, status);
210
0
    if (U_FAILURE(status)) { return; }
211
0
    roundToMagnitude(0, roundingMode, status);
212
0
    if (U_FAILURE(status)) { return; }
213
0
    multiplyBy(incrementDN, status);
214
0
    if (U_FAILURE(status)) { return; }
215
0
}
216
217
2.05k
void DecimalQuantity::multiplyBy(const DecNum& multiplicand, UErrorCode& status) {
218
2.05k
    if (isZeroish()) {
219
30
        return;
220
30
    }
221
    // Convert to DecNum, multiply, and convert back.
222
2.02k
    DecNum decnum;
223
2.02k
    toDecNum(decnum, status);
224
2.02k
    if (U_FAILURE(status)) { return; }
225
2.02k
    decnum.multiplyBy(multiplicand, status);
226
2.02k
    if (U_FAILURE(status)) { return; }
227
1.53k
    setToDecNum(decnum, status);
228
1.53k
}
229
230
0
void DecimalQuantity::divideBy(const DecNum& divisor, UErrorCode& status) {
231
0
    if (isZeroish()) {
232
0
        return;
233
0
    }
234
    // Convert to DecNum, multiply, and convert back.
235
0
    DecNum decnum;
236
0
    toDecNum(decnum, status);
237
0
    if (U_FAILURE(status)) { return; }
238
0
    decnum.divideBy(divisor, status);
239
0
    if (U_FAILURE(status)) { return; }
240
0
    setToDecNum(decnum, status);
241
0
}
242
243
30.7k
void DecimalQuantity::negate() {
244
30.7k
    flags ^= NEGATIVE_FLAG;
245
30.7k
}
246
247
759k
int32_t DecimalQuantity::getMagnitude() const {
248
759k
    U_ASSERT(precision != 0);
249
759k
    return scale + precision - 1;
250
759k
}
251
252
1.46M
bool DecimalQuantity::adjustMagnitude(int32_t delta) {
253
1.46M
    if (precision != 0) {
254
        // i.e., scale += delta; origDelta += delta
255
1.35M
        bool overflow = uprv_add32_overflow(scale, delta, &scale);
256
1.35M
        overflow = uprv_add32_overflow(origDelta, delta, &origDelta) || overflow;
257
        // Make sure that precision + scale won't overflow, either
258
1.35M
        int32_t dummy;
259
1.35M
        overflow = overflow || uprv_add32_overflow(scale, precision, &dummy);
260
1.35M
        return overflow;
261
1.35M
    }
262
112k
    return false;
263
1.46M
}
264
265
16.4k
int32_t DecimalQuantity::adjustToZeroScale() {
266
16.4k
    int32_t retval = scale;
267
16.4k
    scale = 0;
268
16.4k
    return retval;
269
16.4k
}
270
271
4.20M
double DecimalQuantity::getPluralOperand(PluralOperand operand) const {
272
    // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
273
    // See the comment at the top of this file explaining the "isApproximate" field.
274
4.20M
    U_ASSERT(!isApproximate);
275
276
4.20M
    switch (operand) {
277
1.96M
        case PLURAL_OPERAND_I:
278
            // Invert the negative sign if necessary
279
1.96M
            return static_cast<double>(isNegative() ? -toLong(true) : toLong(true));
280
3.18k
        case PLURAL_OPERAND_F:
281
3.18k
            return static_cast<double>(toFractionLong(true));
282
1.29k
        case PLURAL_OPERAND_T:
283
1.29k
            return static_cast<double>(toFractionLong(false));
284
355k
        case PLURAL_OPERAND_V:
285
355k
            return fractionCount();
286
0
        case PLURAL_OPERAND_W:
287
0
            return fractionCountWithoutTrailingZeros();
288
875k
        case PLURAL_OPERAND_E:
289
875k
            return static_cast<double>(getExponent());
290
0
        case PLURAL_OPERAND_C:
291
            // Plural operand `c` is currently an alias for `e`.
292
0
            return static_cast<double>(getExponent());
293
1.00M
        default:
294
1.00M
            return std::abs(toDouble());
295
4.20M
    }
296
4.20M
}
297
298
875k
int32_t DecimalQuantity::getExponent() const {
299
875k
    return exponent;
300
875k
}
301
302
3.26k
void DecimalQuantity::adjustExponent(int delta) {
303
3.26k
    exponent = exponent + delta;
304
3.26k
}
305
306
0
void DecimalQuantity::resetExponent() {
307
0
    adjustMagnitude(exponent);
308
0
    exponent = 0;
309
0
}
310
311
2.41k
bool DecimalQuantity::hasIntegerValue() const {
312
2.41k
    return scale >= 0;
313
2.41k
}
314
315
221M
int32_t DecimalQuantity::getUpperDisplayMagnitude() const {
316
    // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
317
    // See the comment in the header file explaining the "isApproximate" field.
318
221M
    U_ASSERT(!isApproximate);
319
320
221M
    int32_t magnitude = scale + precision;
321
221M
    int32_t result = (lReqPos > magnitude) ? lReqPos : magnitude;
322
221M
    return result - 1;
323
221M
}
324
325
5.09M
int32_t DecimalQuantity::getLowerDisplayMagnitude() const {
326
    // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
327
    // See the comment in the header file explaining the "isApproximate" field.
328
5.09M
    U_ASSERT(!isApproximate);
329
330
5.09M
    int32_t magnitude = scale;
331
5.09M
    int32_t result = (rReqPos < magnitude) ? rReqPos : magnitude;
332
5.09M
    return result;
333
5.09M
}
334
335
1.32G
int8_t DecimalQuantity::getDigit(int32_t magnitude) const {
336
    // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
337
    // See the comment at the top of this file explaining the "isApproximate" field.
338
1.32G
    U_ASSERT(!isApproximate);
339
340
1.32G
    return getDigitPos(magnitude - scale);
341
1.32G
}
342
343
355k
int32_t DecimalQuantity::fractionCount() const {
344
355k
    int32_t fractionCountWithExponent = -getLowerDisplayMagnitude() - exponent;
345
355k
    return fractionCountWithExponent > 0 ? fractionCountWithExponent : 0;
346
355k
}
347
348
0
int32_t DecimalQuantity::fractionCountWithoutTrailingZeros() const {
349
0
    int32_t fractionCountWithExponent = -scale - exponent;
350
0
    return fractionCountWithExponent > 0 ? fractionCountWithExponent : 0;  // max(-fractionCountWithExponent, 0)
351
0
}
352
353
8.77M
bool DecimalQuantity::isNegative() const {
354
8.77M
    return (flags & NEGATIVE_FLAG) != 0;
355
8.77M
}
356
357
2.27M
Signum DecimalQuantity::signum() const {
358
2.27M
    bool isZero = (isZeroish() && !isInfinite());
359
2.27M
    bool isNeg = isNegative();
360
2.27M
    if (isZero && isNeg) {
361
295
        return SIGNUM_NEG_ZERO;
362
2.27M
    } else if (isZero) {
363
1.96M
        return SIGNUM_POS_ZERO;
364
1.96M
    } else if (isNeg) {
365
2.54k
        return SIGNUM_NEG;
366
309k
    } else {
367
309k
        return SIGNUM_POS;
368
309k
    }
369
2.27M
}
370
371
8.73M
bool DecimalQuantity::isInfinite() const {
372
8.73M
    return (flags & INFINITY_FLAG) != 0;
373
8.73M
}
374
375
6.77M
bool DecimalQuantity::isNaN() const {
376
6.77M
    return (flags & NAN_FLAG) != 0;
377
6.77M
}
378
379
5.90M
bool DecimalQuantity::isZeroish() const {
380
5.90M
    return precision == 0;
381
5.90M
}
382
383
0
DecimalQuantity &DecimalQuantity::setToInt(int32_t n) {
384
0
    setBcdToZero();
385
0
    flags = 0;
386
0
    if (n == INT32_MIN) {
387
0
        flags |= NEGATIVE_FLAG;
388
        // leave as INT32_MIN; handled below in _setToInt()
389
0
    } else if (n < 0) {
390
0
        flags |= NEGATIVE_FLAG;
391
0
        n = -n;
392
0
    }
393
0
    if (n != 0) {
394
0
        _setToInt(n);
395
0
        compact();
396
0
    }
397
0
    return *this;
398
0
}
399
400
0
void DecimalQuantity::_setToInt(int32_t n) {
401
0
    if (n == INT32_MIN) {
402
0
        readLongToBcd(-static_cast<int64_t>(n));
403
0
    } else {
404
0
        readIntToBcd(n);
405
0
    }
406
0
}
407
408
114k
DecimalQuantity &DecimalQuantity::setToLong(int64_t n) {
409
114k
    setBcdToZero();
410
114k
    flags = 0;
411
114k
    if (n < 0 && n > INT64_MIN) {
412
1.95k
        flags |= NEGATIVE_FLAG;
413
1.95k
        n = -n;
414
1.95k
    }
415
114k
    if (n != 0) {
416
93.4k
        _setToLong(n);
417
93.4k
        compact();
418
93.4k
    }
419
114k
    return *this;
420
114k
}
421
422
819k
void DecimalQuantity::_setToLong(int64_t n) {
423
819k
    if (n == INT64_MIN) {
424
25
        DecNum decnum;
425
25
        UErrorCode localStatus = U_ZERO_ERROR;
426
25
        decnum.setTo("9.223372036854775808E+18", localStatus);
427
25
        if (U_FAILURE(localStatus)) { return; } // unexpected
428
25
        flags |= NEGATIVE_FLAG;
429
25
        readDecNumberToBcd(decnum);
430
819k
    } else if (n <= INT32_MAX) {
431
87.3k
        readIntToBcd(static_cast<int32_t>(n));
432
732k
    } else {
433
732k
        readLongToBcd(n);
434
732k
    }
435
819k
}
436
437
2.29M
DecimalQuantity &DecimalQuantity::setToDouble(double n) {
438
2.29M
    setBcdToZero();
439
2.29M
    flags = 0;
440
    // signbit() from <math.h> handles +0.0 vs -0.0
441
2.29M
    if (std::signbit(n)) {
442
1.21k
        flags |= NEGATIVE_FLAG;
443
1.21k
        n = -n;
444
1.21k
    }
445
2.29M
    if (std::isnan(n) != 0) {
446
2.99k
        flags |= NAN_FLAG;
447
2.28M
    } else if (std::isfinite(n) == 0) {
448
433
        flags |= INFINITY_FLAG;
449
2.28M
    } else if (n != 0) {
450
795k
        _setToDoubleFast(n);
451
795k
        compact();
452
795k
    }
453
2.29M
    return *this;
454
2.29M
}
455
456
795k
void DecimalQuantity::_setToDoubleFast(double n) {
457
795k
    isApproximate = true;
458
795k
    origDouble = n;
459
795k
    origDelta = 0;
460
461
    // Make sure the double is an IEEE 754 double.  If not, fall back to the slow path right now.
462
    // TODO: Make a fast path for other types of doubles.
463
795k
    if (!std::numeric_limits<double>::is_iec559) {
464
0
        convertToAccurateDouble();
465
0
        return;
466
0
    }
467
468
    // To get the bits from the double, use memcpy, which takes care of endianness.
469
795k
    uint64_t ieeeBits;
470
795k
    uprv_memcpy(&ieeeBits, &n, sizeof(n));
471
795k
    int32_t exponent = static_cast<int32_t>((ieeeBits & 0x7ff0000000000000L) >> 52) - 0x3ff;
472
473
    // Not all integers can be represented exactly for exponent > 52
474
795k
    if (exponent <= 52 && static_cast<int64_t>(n) == n) {
475
13.8k
        _setToLong(static_cast<int64_t>(n));
476
13.8k
        return;
477
13.8k
    }
478
479
781k
    if (exponent == -1023 || exponent == 1024) {
480
        // The extreme values of exponent are special; use slow path.
481
69.7k
        convertToAccurateDouble();
482
69.7k
        return;
483
69.7k
    }
484
485
    // 3.3219... is log2(10)
486
712k
    auto fracLength = static_cast<int32_t> ((52 - exponent) / 3.32192809488736234787031942948939017586);
487
712k
    if (fracLength >= 0) {
488
427k
        int32_t i = fracLength;
489
        // 1e22 is the largest exact double.
490
3.26M
        for (; i >= 22; i -= 22) n *= 1e22;
491
427k
        n *= DOUBLE_MULTIPLIERS[i];
492
427k
    } else {
493
284k
        int32_t i = fracLength;
494
        // 1e22 is the largest exact double.
495
2.11M
        for (; i <= -22; i += 22) n /= 1e22;
496
284k
        n /= DOUBLE_MULTIPLIERS[-i];
497
284k
    }
498
712k
    auto result = static_cast<int64_t>(uprv_round(n));
499
712k
    if (result != 0) {
500
712k
        _setToLong(result);
501
712k
        scale -= fracLength;
502
712k
    }
503
712k
}
504
505
379k
void DecimalQuantity::convertToAccurateDouble() {
506
379k
    U_ASSERT(origDouble != 0);
507
379k
    int32_t delta = origDelta;
508
509
    // Call the slow oracle function (Double.toString in Java, DoubleToAscii in C++).
510
379k
    char buffer[DoubleToStringConverter::kBase10MaximalLength + 1];
511
379k
    bool sign; // unused; always positive
512
379k
    int32_t length;
513
379k
    int32_t point;
514
379k
    DoubleToStringConverter::DoubleToAscii(
515
379k
        origDouble,
516
379k
        DoubleToStringConverter::DtoaMode::SHORTEST,
517
379k
        0,
518
379k
        buffer,
519
379k
        sizeof(buffer),
520
379k
        &sign,
521
379k
        &length,
522
379k
        &point
523
379k
    );
524
525
379k
    setBcdToZero();
526
379k
    readDoubleConversionToBcd(buffer, length, point);
527
379k
    scale += delta;
528
379k
    explicitExactDouble = true;
529
379k
}
530
531
1.70k
DecimalQuantity &DecimalQuantity::setToDecNumber(StringPiece n, UErrorCode& status) {
532
1.70k
    setBcdToZero();
533
1.70k
    flags = 0;
534
535
    // Compute the decNumber representation
536
1.70k
    DecNum decnum;
537
1.70k
    decnum.setTo(n, status);
538
539
1.70k
    _setToDecNum(decnum, status);
540
1.70k
    return *this;
541
1.70k
}
542
543
1.53k
DecimalQuantity& DecimalQuantity::setToDecNum(const DecNum& decnum, UErrorCode& status) {
544
1.53k
    setBcdToZero();
545
1.53k
    flags = 0;
546
547
1.53k
    _setToDecNum(decnum, status);
548
1.53k
    return *this;
549
1.53k
}
550
551
3.23k
void DecimalQuantity::_setToDecNum(const DecNum& decnum, UErrorCode& status) {
552
3.23k
    if (U_FAILURE(status)) { return; }
553
3.23k
    if (decnum.isNegative()) {
554
566
        flags |= NEGATIVE_FLAG;
555
566
    }
556
3.23k
    if (decnum.isNaN()) {
557
0
        flags |= NAN_FLAG;
558
3.23k
    } else if (decnum.isInfinity()) {
559
0
        flags |= INFINITY_FLAG;
560
3.23k
    } else if (!decnum.isZero()) {
561
3.18k
        readDecNumberToBcd(decnum);
562
3.18k
        compact();
563
3.18k
    }
564
3.23k
}
565
566
0
DecimalQuantity DecimalQuantity::fromExponentString(UnicodeString num, UErrorCode& status) {
567
0
    if (num.indexOf(u'e') >= 0 || num.indexOf(u'c') >= 0
568
0
                || num.indexOf(u'E') >= 0 || num.indexOf(u'C') >= 0) {
569
0
        int32_t ePos = num.lastIndexOf('e');
570
0
        if (ePos < 0) {
571
0
            ePos = num.lastIndexOf('c');
572
0
        }
573
0
        if (ePos < 0) {
574
0
            ePos = num.lastIndexOf('E');
575
0
        }
576
0
        if (ePos < 0) {
577
0
            ePos = num.lastIndexOf('C');
578
0
        }
579
0
        int32_t expNumPos = ePos + 1;
580
0
        UnicodeString exponentStr = num.tempSubString(expNumPos, num.length() - expNumPos);
581
582
        // parse exponentStr into exponent, but note that parseAsciiInteger doesn't handle the minus sign
583
0
        bool isExpStrNeg = num[expNumPos] == u'-';
584
0
        int32_t exponentParsePos = isExpStrNeg ? 1 : 0;
585
0
        int32_t exponent = ICU_Utility::parseAsciiInteger(exponentStr, exponentParsePos);
586
0
        exponent = isExpStrNeg ? -exponent : exponent;
587
588
        // Compute the decNumber representation
589
0
        UnicodeString fractionStr = num.tempSubString(0, ePos);
590
0
        CharString fracCharStr = CharString();
591
0
        fracCharStr.appendInvariantChars(fractionStr, status);
592
0
        DecNum decnum;
593
0
        decnum.setTo(fracCharStr.toStringPiece(), status);
594
595
        // Clear and set this DecimalQuantity instance
596
0
        DecimalQuantity dq;
597
0
        dq.setToDecNum(decnum, status);
598
0
        int32_t numFracDigit = getVisibleFractionCount(fractionStr);
599
0
        dq.setMinFraction(numFracDigit);
600
0
        dq.adjustExponent(exponent);
601
602
0
        return dq;
603
0
    } else {
604
0
        DecimalQuantity dq;
605
0
        int numFracDigit = getVisibleFractionCount(num);
606
607
0
        CharString numCharStr = CharString();
608
0
        numCharStr.appendInvariantChars(num, status);
609
0
        dq.setToDecNumber(numCharStr.toStringPiece(), status);
610
611
0
        dq.setMinFraction(numFracDigit);
612
0
        return dq;
613
0
    }
614
0
}
615
616
0
int32_t DecimalQuantity::getVisibleFractionCount(UnicodeString value) {
617
0
    int decimalPos = value.indexOf('.') + 1;
618
0
    if (decimalPos == 0) {
619
0
        return 0;
620
0
    } else {
621
0
        return value.length() - decimalPos;
622
0
    }
623
0
}
624
625
2.64M
int64_t DecimalQuantity::toLong(bool truncateIfOverflow) const {
626
    // NOTE: Call sites should be guarded by fitsInLong(), like this:
627
    // if (dq.fitsInLong()) { /* use dq.toLong() */ } else { /* use some fallback */ }
628
    // Fallback behavior upon truncateIfOverflow is to truncate at 17 digits.
629
2.64M
    uint64_t result = 0L;
630
2.64M
    int32_t upperMagnitude = exponent + scale + precision - 1;
631
2.64M
    if (truncateIfOverflow) {
632
1.97M
        upperMagnitude = std::min(upperMagnitude, 17);
633
1.97M
    }
634
7.56M
    for (int32_t magnitude = upperMagnitude; magnitude >= 0; magnitude--) {
635
4.92M
        result = result * 10 + getDigitPos(magnitude - scale - exponent);
636
4.92M
    }
637
2.64M
    if (isNegative()) {
638
23.0k
        return static_cast<int64_t>(0LL - result); // i.e., -result
639
23.0k
    }
640
2.61M
    return static_cast<int64_t>(result);
641
2.64M
}
642
643
4.47k
uint64_t DecimalQuantity::toFractionLong(bool includeTrailingZeros) const {
644
4.47k
    uint64_t result = 0L;
645
4.47k
    int32_t magnitude = -1 - exponent;
646
4.47k
    int32_t lowerMagnitude = scale;
647
4.47k
    if (includeTrailingZeros) {
648
3.18k
        lowerMagnitude = std::min(lowerMagnitude, rReqPos);
649
3.18k
    }
650
197M
    for (; magnitude >= lowerMagnitude && result <= 1e18L; magnitude--) {
651
197M
        result = result * 10 + getDigitPos(magnitude - scale);
652
197M
    }
653
    // Remove trailing zeros; this can happen during integer overflow cases.
654
4.47k
    if (!includeTrailingZeros) {
655
1.33k
        while (result > 0 && (result % 10) == 0) {
656
44
            result /= 10;
657
44
        }
658
1.29k
    }
659
4.47k
    return result;
660
4.47k
}
661
662
853k
bool DecimalQuantity::fitsInLong(bool ignoreFraction) const {
663
853k
    if (isInfinite() || isNaN()) {
664
0
        return false;
665
0
    }
666
853k
    if (isZeroish()) {
667
20.8k
        return true;
668
20.8k
    }
669
833k
    if (exponent + scale < 0 && !ignoreFraction) {
670
171k
        return false;
671
171k
    }
672
661k
    int magnitude = getMagnitude();
673
661k
    if (magnitude < 18) {
674
631k
        return true;
675
631k
    }
676
30.3k
    if (magnitude > 18) {
677
28.6k
        return false;
678
28.6k
    }
679
    // Hard case: the magnitude is 10^18.
680
    // The largest int64 is: 9,223,372,036,854,775,807
681
3.01k
    for (int p = 0; p < precision; p++) {
682
2.45k
        int8_t digit = getDigit(18 - p);
683
2.45k
        static int8_t INT64_BCD[] = { 9, 2, 2, 3, 3, 7, 2, 0, 3, 6, 8, 5, 4, 7, 7, 5, 8, 0, 8 };
684
2.45k
        if (digit < INT64_BCD[p]) {
685
943
            return true;
686
1.50k
        } else if (digit > INT64_BCD[p]) {
687
256
            return false;
688
256
        }
689
2.45k
    }
690
    // Exactly equal to max long plus one.
691
565
    return isNegative();
692
1.76k
}
693
694
1.27M
double DecimalQuantity::toDouble() const {
695
    // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
696
    // See the comment in the header file explaining the "isApproximate" field.
697
1.27M
    U_ASSERT(!isApproximate);
698
699
1.27M
    if (isNaN()) {
700
0
        return NAN;
701
1.27M
    } else if (isInfinite()) {
702
0
        return isNegative() ? -INFINITY : INFINITY;
703
0
    }
704
705
    // We are processing well-formed input, so we don't need any special options to StringToDoubleConverter.
706
1.27M
    StringToDoubleConverter converter(0, 0, 0, "", "");
707
1.27M
    UnicodeString numberString = this->toScientificString();
708
1.27M
    int32_t count;
709
1.27M
    return converter.StringToDouble(
710
1.27M
            reinterpret_cast<const uint16_t*>(numberString.getBuffer()),
711
1.27M
            numberString.length(),
712
1.27M
            &count);
713
1.27M
}
714
715
2.02k
DecNum& DecimalQuantity::toDecNum(DecNum& output, UErrorCode& status) const {
716
    // Special handling for zero
717
2.02k
    if (precision == 0) {
718
0
        output.setTo("0", status);
719
0
        return output;
720
0
    }
721
722
    // Use the BCD constructor. We need to do a little bit of work to convert, though.
723
    // The decNumber constructor expects most-significant first, but we store least-significant first.
724
2.02k
    MaybeStackArray<uint8_t, 20> ubcd(precision, status);
725
2.02k
    if (U_FAILURE(status)) {
726
0
        return output;
727
0
    }
728
32.2k
    for (int32_t m = 0; m < precision; m++) {
729
30.1k
        ubcd[precision - m - 1] = static_cast<uint8_t>(getDigitPos(m));
730
30.1k
    }
731
2.02k
    output.setTo(ubcd.getAlias(), precision, scale, isNegative(), status);
732
2.02k
    return output;
733
2.02k
}
734
735
0
void DecimalQuantity::truncate() {
736
0
    if (scale < 0) {
737
0
        shiftRight(-scale);
738
0
        scale = 0;
739
0
        compact();
740
0
    }
741
0
}
742
743
0
void DecimalQuantity::roundToNickel(int32_t magnitude, RoundingMode roundingMode, UErrorCode& status) {
744
0
    roundToMagnitude(magnitude, roundingMode, true, status);
745
0
}
746
747
2.27M
void DecimalQuantity::roundToMagnitude(int32_t magnitude, RoundingMode roundingMode, UErrorCode& status) {
748
2.27M
    roundToMagnitude(magnitude, roundingMode, false, status);
749
2.27M
}
750
751
2.57M
void DecimalQuantity::roundToMagnitude(int32_t magnitude, RoundingMode roundingMode, bool nickel, UErrorCode& status) {
752
    // The position in the BCD at which rounding will be performed; digits to the right of position
753
    // will be rounded away.
754
2.57M
    int position = safeSubtract(magnitude, scale);
755
756
    // "trailing" = least significant digit to the left of rounding
757
2.57M
    int8_t trailingDigit = getDigitPos(position);
758
759
2.57M
    if (position <= 0 && !isApproximate && (!nickel || trailingDigit == 0 || trailingDigit == 5)) {
760
        // All digits are to the left of the rounding magnitude.
761
1.78M
    } else if (precision == 0) {
762
        // No rounding for zero.
763
787k
    } else {
764
        // Perform rounding logic.
765
        // "leading" = most significant digit to the right of rounding
766
787k
        int8_t leadingDigit = getDigitPos(safeSubtract(position, 1));
767
768
        // Compute which section of the number we are in.
769
        // EDGE means we are at the bottom or top edge, like 1.000 or 1.999 (used by doubles)
770
        // LOWER means we are between the bottom edge and the midpoint, like 1.391
771
        // MIDPOINT means we are exactly in the middle, like 1.500
772
        // UPPER means we are between the midpoint and the top edge, like 1.916
773
787k
        roundingutils::Section section;
774
787k
        if (!isApproximate) {
775
78.3k
            if (nickel && trailingDigit != 2 && trailingDigit != 7) {
776
                // Nickel rounding, and not at .02x or .07x
777
0
                if (trailingDigit < 2) {
778
                    // .00, .01 => down to .00
779
0
                    section = roundingutils::SECTION_LOWER;
780
0
                } else if (trailingDigit < 5) {
781
                    // .03, .04 => up to .05
782
0
                    section = roundingutils::SECTION_UPPER;
783
0
                } else if (trailingDigit < 7) {
784
                    // .05, .06 => down to .05
785
0
                    section = roundingutils::SECTION_LOWER;
786
0
                } else {
787
                    // .08, .09 => up to .10
788
0
                    section = roundingutils::SECTION_UPPER;
789
0
                }
790
78.3k
            } else if (leadingDigit < 5) {
791
                // Includes nickel rounding .020-.024 and .070-.074
792
72.5k
                section = roundingutils::SECTION_LOWER;
793
72.5k
            } else if (leadingDigit > 5) {
794
                // Includes nickel rounding .026-.029 and .076-.079
795
3.85k
                section = roundingutils::SECTION_UPPER;
796
3.85k
            } else {
797
                // Includes nickel rounding .025 and .075
798
1.94k
                section = roundingutils::SECTION_MIDPOINT;
799
11.3k
                for (int p = safeSubtract(position, 2); p >= 0; p--) {
800
10.9k
                    if (getDigitPos(p) != 0) {
801
1.49k
                        section = roundingutils::SECTION_UPPER;
802
1.49k
                        break;
803
1.49k
                    }
804
10.9k
                }
805
1.94k
            }
806
709k
        } else {
807
709k
            int32_t p = safeSubtract(position, 2);
808
709k
            int32_t minP = uprv_max(0, precision - 14);
809
709k
            if (leadingDigit == 0 && (!nickel || trailingDigit == 0 || trailingDigit == 5)) {
810
692k
                section = roundingutils::SECTION_LOWER_EDGE;
811
1.07G
                for (; p >= minP; p--) {
812
1.07G
                    if (getDigitPos(p) != 0) {
813
403k
                        section = roundingutils::SECTION_LOWER;
814
403k
                        break;
815
403k
                    }
816
1.07G
                }
817
692k
            } else if (leadingDigit == 4 && (!nickel || trailingDigit == 2 || trailingDigit == 7)) {
818
2.10k
                section = roundingutils::SECTION_MIDPOINT;
819
8.91k
                for (; p >= minP; p--) {
820
7.71k
                    if (getDigitPos(p) != 9) {
821
912
                        section = roundingutils::SECTION_LOWER;
822
912
                        break;
823
912
                    }
824
7.71k
                }
825
14.8k
            } else if (leadingDigit == 5 && (!nickel || trailingDigit == 2 || trailingDigit == 7)) {
826
3.76k
                section = roundingutils::SECTION_MIDPOINT;
827
13.2k
                for (; p >= minP; p--) {
828
11.5k
                    if (getDigitPos(p) != 0) {
829
2.07k
                        section = roundingutils::SECTION_UPPER;
830
2.07k
                        break;
831
2.07k
                    }
832
11.5k
                }
833
11.0k
            } else if (leadingDigit == 9 && (!nickel || trailingDigit == 4 || trailingDigit == 9)) {
834
3.51k
                section = roundingutils::SECTION_UPPER_EDGE;
835
6.96k
                for (; p >= minP; p--) {
836
5.19k
                    if (getDigitPos(p) != 9) {
837
1.74k
                        section = roundingutils::SECTION_UPPER;
838
1.74k
                        break;
839
1.74k
                    }
840
5.19k
                }
841
7.57k
            } else if (nickel && trailingDigit != 2 && trailingDigit != 7) {
842
                // Nickel rounding, and not at .02x or .07x
843
0
                if (trailingDigit < 2) {
844
                    // .00, .01 => down to .00
845
0
                    section = roundingutils::SECTION_LOWER;
846
0
                } else if (trailingDigit < 5) {
847
                    // .03, .04 => up to .05
848
0
                    section = roundingutils::SECTION_UPPER;
849
0
                } else if (trailingDigit < 7) {
850
                    // .05, .06 => down to .05
851
0
                    section = roundingutils::SECTION_LOWER;
852
0
                } else {
853
                    // .08, .09 => up to .10
854
0
                    section = roundingutils::SECTION_UPPER;
855
0
                }
856
7.57k
            } else if (leadingDigit < 5) {
857
                // Includes nickel rounding .020-.024 and .070-.074
858
2.81k
                section = roundingutils::SECTION_LOWER;
859
4.76k
            } else {
860
                // Includes nickel rounding .026-.029 and .076-.079
861
4.76k
                section = roundingutils::SECTION_UPPER;
862
4.76k
            }
863
864
709k
            bool roundsAtMidpoint = roundingutils::roundsAtMidpoint(roundingMode);
865
709k
            if (safeSubtract(position, 1) < precision - 14 ||
866
418k
                (roundsAtMidpoint && section == roundingutils::SECTION_MIDPOINT) ||
867
416k
                (!roundsAtMidpoint && section < 0 /* i.e. at upper or lower edge */)) {
868
                // Oops! This means that we have to get the exact representation of the double,
869
                // because the zone of uncertainty is along the rounding boundary.
870
293k
                convertToAccurateDouble();
871
293k
                roundToMagnitude(magnitude, roundingMode, nickel, status); // start over
872
293k
                return;
873
293k
            }
874
875
            // Turn off the approximate double flag, since the value is now confirmed to be exact.
876
416k
            isApproximate = false;
877
416k
            origDouble = 0.0;
878
416k
            origDelta = 0;
879
880
416k
            if (position <= 0 && (!nickel || trailingDigit == 0 || trailingDigit == 5)) {
881
                // All digits are to the left of the rounding magnitude.
882
996
                return;
883
996
            }
884
885
            // Good to continue rounding.
886
415k
            if (section == -1) { section = roundingutils::SECTION_LOWER; }
887
415k
            if (section == -2) { section = roundingutils::SECTION_UPPER; }
888
415k
        }
889
890
        // Nickel rounding "half even" goes to the nearest whole (away from the 5).
891
493k
        bool isEven = nickel
892
493k
                ? (trailingDigit < 2 || trailingDigit > 7
893
0
                        || (trailingDigit == 2 && section != roundingutils::SECTION_UPPER)
894
0
                        || (trailingDigit == 7 && section == roundingutils::SECTION_UPPER))
895
493k
                : (trailingDigit % 2) == 0;
896
897
493k
        bool roundDown = roundingutils::getRoundingDirection(isEven,
898
493k
                isNegative(),
899
493k
                section,
900
493k
                roundingMode,
901
493k
                status);
902
493k
        if (U_FAILURE(status)) {
903
0
            return;
904
0
        }
905
906
        // Perform truncation
907
493k
        if (position >= precision) {
908
471k
            U_ASSERT(trailingDigit == 0);
909
471k
            setBcdToZero();
910
471k
            scale = magnitude;
911
471k
        } else {
912
21.4k
            shiftRight(position);
913
21.4k
        }
914
915
493k
        if (nickel) {
916
0
            if (trailingDigit < 5 && roundDown) {
917
0
                setDigitPos(0, 0);
918
0
                compact();
919
0
                return;
920
0
            } else if (trailingDigit >= 5 && !roundDown) {
921
0
                setDigitPos(0, 9);
922
0
                trailingDigit = 9;
923
                // do not return: use the bubbling logic below
924
0
            } else {
925
0
                setDigitPos(0, 5);
926
                // If the quantity was set to 0, we may need to restore a digit.
927
0
                if (precision == 0) {
928
0
                    precision = 1;
929
0
                }
930
                // compact not necessary: digit at position 0 is nonzero
931
0
                return;
932
0
            }
933
0
        }
934
935
        // Bubble the result to the higher digits
936
493k
        if (!roundDown) {
937
13.6k
            if (trailingDigit == 9) {
938
3.87k
                int bubblePos = 0;
939
                // Note: in the long implementation, the most digits BCD can have at this point is
940
                // 15, so bubblePos <= 15 and getDigitPos(bubblePos) is safe.
941
14.8k
                for (; getDigitPos(bubblePos) == 9; bubblePos++) {}
942
3.87k
                shiftRight(bubblePos); // shift off the trailing 9s
943
3.87k
            }
944
13.6k
            int8_t digit0 = getDigitPos(0);
945
13.6k
            U_ASSERT(digit0 != 9);
946
13.6k
            setDigitPos(0, static_cast<int8_t>(digit0 + 1));
947
13.6k
            precision += 1; // in case an extra digit got added
948
13.6k
        }
949
950
493k
        compact();
951
493k
    }
952
2.57M
}
953
954
16.9k
void DecimalQuantity::roundToInfinity() {
955
16.9k
    if (isApproximate) {
956
16.4k
        convertToAccurateDouble();
957
16.4k
    }
958
16.9k
}
959
960
78.0M
void DecimalQuantity::appendDigit(int8_t value, int32_t leadingZeros, bool appendAsInteger) {
961
78.0M
    U_ASSERT(leadingZeros >= 0);
962
963
    // Zero requires special handling to maintain the invariant that the least-significant digit
964
    // in the BCD is nonzero.
965
78.0M
    if (value == 0) {
966
40.7M
        if (appendAsInteger && precision != 0) {
967
40.0M
            scale += leadingZeros + 1;
968
40.0M
        }
969
40.7M
        return;
970
40.7M
    }
971
972
    // Deal with trailing zeros
973
37.3M
    if (scale > 0) {
974
2.08M
        leadingZeros += scale;
975
2.08M
        if (appendAsInteger) {
976
2.08M
            scale = 0;
977
2.08M
        }
978
2.08M
    }
979
980
    // Append digit
981
37.3M
    shiftLeft(leadingZeros + 1);
982
37.3M
    setDigitPos(0, value);
983
984
    // Fix scale if in integer mode
985
37.3M
    if (appendAsInteger) {
986
36.6M
        scale += leadingZeros + 1;
987
36.6M
    }
988
37.3M
}
989
990
0
UnicodeString DecimalQuantity::toPlainString() const {
991
0
    U_ASSERT(!isApproximate);
992
0
    UnicodeString sb;
993
0
    if (isNegative()) {
994
0
        sb.append(u'-');
995
0
    }
996
0
    if (precision == 0) {
997
0
        sb.append(u'0');
998
0
        return sb;
999
0
    }
1000
0
    int32_t upper = scale + precision + exponent - 1;
1001
0
    int32_t lower = scale + exponent;
1002
0
    if (upper < lReqPos - 1) {
1003
0
        upper = lReqPos - 1;
1004
0
    }
1005
0
    if (lower > rReqPos) {
1006
0
        lower = rReqPos;
1007
0
    }    
1008
0
    int32_t p = upper;
1009
0
    if (p < 0) {
1010
0
        sb.append(u'0');
1011
0
    }
1012
0
    for (; p >= 0; p--) {
1013
0
        sb.append(u'0' + getDigitPos(p - scale - exponent));
1014
0
    }
1015
0
    if (lower < 0) {
1016
0
        sb.append(u'.');
1017
0
    }
1018
0
    for(; p >= lower; p--) {
1019
0
        sb.append(u'0' + getDigitPos(p - scale - exponent));
1020
0
    }
1021
0
    return sb;
1022
0
}
1023
1024
1025
0
UnicodeString DecimalQuantity::toExponentString() const {
1026
0
    U_ASSERT(!isApproximate);
1027
0
    UnicodeString sb;
1028
0
    if (isNegative()) {
1029
0
        sb.append(u'-');
1030
0
    }
1031
1032
0
    int32_t upper = scale + precision - 1;
1033
0
    int32_t lower = scale;
1034
0
    if (upper < lReqPos - 1) {
1035
0
        upper = lReqPos - 1;
1036
0
    }
1037
0
    if (lower > rReqPos) {
1038
0
        lower = rReqPos;
1039
0
    }    
1040
0
    int32_t p = upper;
1041
0
    if (p < 0) {
1042
0
        sb.append(u'0');
1043
0
    }
1044
0
    for (; p >= 0; p--) {
1045
0
        sb.append(u'0' + getDigitPos(p - scale));
1046
0
    }
1047
0
    if (lower < 0) {
1048
0
        sb.append(u'.');
1049
0
    }
1050
0
    for(; p >= lower; p--) {
1051
0
        sb.append(u'0' + getDigitPos(p - scale));
1052
0
    }
1053
1054
0
    if (exponent != 0) {
1055
0
        sb.append(u'c');
1056
0
        ICU_Utility::appendNumber(sb, exponent);        
1057
0
    }
1058
1059
0
    return sb;
1060
0
}
1061
1062
1.27M
UnicodeString DecimalQuantity::toScientificString() const {
1063
1.27M
    U_ASSERT(!isApproximate);
1064
1.27M
    UnicodeString result;
1065
1.27M
    if (isNegative()) {
1066
7.51k
        result.append(u'-');
1067
7.51k
    }
1068
1.27M
    if (precision == 0) {
1069
702k
        result.append(u"0E+0", -1);
1070
702k
        return result;
1071
702k
    }
1072
569k
    int32_t upperPos = precision - 1;
1073
569k
    int32_t lowerPos = 0;
1074
569k
    int32_t p = upperPos;
1075
569k
    result.append(u'0' + getDigitPos(p));
1076
569k
    if ((--p) >= lowerPos) {
1077
422k
        result.append(u'.');
1078
26.1M
        for (; p >= lowerPos; p--) {
1079
25.7M
            result.append(u'0' + getDigitPos(p));
1080
25.7M
        }
1081
422k
    }
1082
569k
    result.append(u'E');
1083
569k
    int32_t _scale = upperPos + scale + exponent;
1084
569k
    if (_scale == INT32_MIN) {
1085
218
        result.append(u"-2147483648");
1086
218
        return result;
1087
568k
    } else if (_scale < 0) {
1088
131k
        _scale *= -1;
1089
131k
        result.append(u'-');
1090
437k
    } else {
1091
437k
        result.append(u'+');
1092
437k
    }
1093
568k
    if (_scale == 0) {
1094
66.7k
        result.append(u'0');
1095
66.7k
    }
1096
568k
    int32_t insertIndex = result.length();
1097
1.73M
    while (_scale > 0) {
1098
1.16M
        std::div_t res = std::div(_scale, 10);
1099
1.16M
        result.insert(insertIndex, u'0' + res.rem);
1100
1.16M
        _scale = res.quot;
1101
1.16M
    }
1102
568k
    return result;
1103
569k
}
1104
1105
////////////////////////////////////////////////////
1106
/// End of DecimalQuantity_AbstractBCD.java      ///
1107
/// Start of DecimalQuantity_DualStorageBCD.java ///
1108
////////////////////////////////////////////////////
1109
1110
2.62G
int8_t DecimalQuantity::getDigitPos(int32_t position) const {
1111
2.62G
    if (usingBytes) {
1112
926M
        if (position < 0 || position >= precision) { return 0; }
1113
23.3M
        return fBCD.bcdBytes.ptr[position];
1114
1.70G
    } else {
1115
1.70G
        if (position < 0 || position >= 16) { return 0; }
1116
15.5M
        return static_cast<int8_t>((fBCD.bcdLong >> (position * 4)) & 0xf);
1117
1.70G
    }
1118
2.62G
}
1119
1120
37.3M
void DecimalQuantity::setDigitPos(int32_t position, int8_t value) {
1121
37.3M
    U_ASSERT(position >= 0);
1122
37.3M
    if (usingBytes) {
1123
31.1M
        ensureCapacity(position + 1);
1124
31.1M
        fBCD.bcdBytes.ptr[position] = value;
1125
31.1M
    } else if (position >= 16) {
1126
0
        switchStorage();
1127
0
        ensureCapacity(position + 1);
1128
0
        fBCD.bcdBytes.ptr[position] = value;
1129
6.22M
    } else {
1130
6.22M
        int shift = position * 4;
1131
6.22M
        fBCD.bcdLong = (fBCD.bcdLong & ~(0xfL << shift)) | (static_cast<long>(value) << shift);
1132
6.22M
    }
1133
37.3M
}
1134
1135
37.3M
void DecimalQuantity::shiftLeft(int32_t numDigits) {
1136
37.3M
    if (!usingBytes && precision + numDigits >= 16) {
1137
41.2k
        switchStorage();
1138
41.2k
    }
1139
37.3M
    if (usingBytes) {
1140
31.1M
        ensureCapacity(precision + numDigits);
1141
31.1M
        uprv_memmove(fBCD.bcdBytes.ptr + numDigits, fBCD.bcdBytes.ptr, precision);
1142
31.1M
        uprv_memset(fBCD.bcdBytes.ptr, 0, numDigits);
1143
31.1M
    } else {
1144
6.21M
        fBCD.bcdLong <<= (numDigits * 4);
1145
6.21M
    }
1146
37.3M
    scale -= numDigits;
1147
37.3M
    precision += numDigits;
1148
37.3M
}
1149
1150
277k
void DecimalQuantity::shiftRight(int32_t numDigits) {
1151
277k
    if (usingBytes) {
1152
257k
        int i = 0;
1153
4.52M
        for (; i < precision - numDigits; i++) {
1154
4.27M
            fBCD.bcdBytes.ptr[i] = fBCD.bcdBytes.ptr[i + numDigits];
1155
4.27M
        }
1156
342k
        for (; i < precision; i++) {
1157
85.1k
            fBCD.bcdBytes.ptr[i] = 0;
1158
85.1k
        }
1159
257k
    } else {
1160
19.8k
        fBCD.bcdLong >>= (numDigits * 4);
1161
19.8k
    }
1162
277k
    scale += numDigits;
1163
277k
    precision -= numDigits;
1164
277k
}
1165
1166
1.08k
void DecimalQuantity::popFromLeft(int32_t numDigits) {
1167
1.08k
    U_ASSERT(numDigits <= precision);
1168
1.08k
    if (usingBytes) {
1169
0
        int i = precision - 1;
1170
0
        for (; i >= precision - numDigits; i--) {
1171
0
            fBCD.bcdBytes.ptr[i] = 0;
1172
0
        }
1173
1.08k
    } else {
1174
1.08k
        fBCD.bcdLong &= (static_cast<uint64_t>(1) << ((precision - numDigits) * 4)) - 1;
1175
1.08k
    }
1176
1.08k
    precision -= numDigits;
1177
1.08k
}
1178
1179
20.0M
void DecimalQuantity::setBcdToZero() {
1180
20.0M
    if (usingBytes) {
1181
210k
        uprv_free(fBCD.bcdBytes.ptr);
1182
210k
        fBCD.bcdBytes.ptr = nullptr;
1183
210k
        usingBytes = false;
1184
210k
    }
1185
20.0M
    fBCD.bcdLong = 0L;
1186
20.0M
    scale = 0;
1187
20.0M
    precision = 0;
1188
20.0M
    isApproximate = false;
1189
20.0M
    origDouble = 0;
1190
20.0M
    origDelta = 0;
1191
20.0M
    exponent = 0;
1192
20.0M
}
1193
1194
87.3k
void DecimalQuantity::readIntToBcd(int32_t n) {
1195
87.3k
    U_ASSERT(n != 0);
1196
    // ints always fit inside the long implementation.
1197
87.3k
    uint64_t result = 0L;
1198
87.3k
    int i = 16;
1199
323k
    for (; n != 0; n /= 10, i--) {
1200
236k
        result = (result >> 4) + ((static_cast<uint64_t>(n) % 10) << 60);
1201
236k
    }
1202
87.3k
    U_ASSERT(!usingBytes);
1203
87.3k
    fBCD.bcdLong = result >> (i * 4);
1204
87.3k
    scale = 0;
1205
87.3k
    precision = 16 - i;
1206
87.3k
}
1207
1208
732k
void DecimalQuantity::readLongToBcd(int64_t n) {
1209
732k
    U_ASSERT(n != 0);
1210
732k
    if (n >= 10000000000000000L) {
1211
244k
        ensureCapacity();
1212
244k
        int i = 0;
1213
4.40M
        for (; n != 0L; n /= 10L, i++) {
1214
4.16M
            fBCD.bcdBytes.ptr[i] = static_cast<int8_t>(n % 10);
1215
4.16M
        }
1216
244k
        U_ASSERT(usingBytes);
1217
244k
        scale = 0;
1218
244k
        precision = i;
1219
487k
    } else {
1220
487k
        uint64_t result = 0L;
1221
487k
        int i = 16;
1222
8.15M
        for (; n != 0L; n /= 10L, i--) {
1223
7.66M
            result = (result >> 4) + ((n % 10) << 60);
1224
7.66M
        }
1225
487k
        U_ASSERT(i >= 0);
1226
487k
        U_ASSERT(!usingBytes);
1227
487k
        fBCD.bcdLong = result >> (i * 4);
1228
487k
        scale = 0;
1229
487k
        precision = 16 - i;
1230
487k
    }
1231
732k
}
1232
1233
3.21k
void DecimalQuantity::readDecNumberToBcd(const DecNum& decnum) {
1234
3.21k
    const decNumber* dn = decnum.getRawDecNumber();
1235
3.21k
    if (dn->digits > 16) {
1236
995
        ensureCapacity(dn->digits);
1237
21.1k
        for (int32_t i = 0; i < dn->digits; i++) {
1238
20.1k
            fBCD.bcdBytes.ptr[i] = dn->lsu[i];
1239
20.1k
        }
1240
2.21k
    } else {
1241
2.21k
        uint64_t result = 0L;
1242
12.2k
        for (int32_t i = 0; i < dn->digits; i++) {
1243
9.99k
            result |= static_cast<uint64_t>(dn->lsu[i]) << (4 * i);
1244
9.99k
        }
1245
2.21k
        fBCD.bcdLong = result;
1246
2.21k
    }
1247
3.21k
    scale = dn->exponent;
1248
3.21k
    precision = dn->digits;
1249
3.21k
}
1250
1251
void DecimalQuantity::readDoubleConversionToBcd(
1252
379k
        const char* buffer, int32_t length, int32_t point) {
1253
    // NOTE: Despite the fact that double-conversion's API is called
1254
    // "DoubleToAscii", they actually use '0' (as opposed to u8'0').
1255
379k
    if (length > 16) {
1256
82.7k
        ensureCapacity(length);
1257
1.48M
        for (int32_t i = 0; i < length; i++) {
1258
1.40M
            fBCD.bcdBytes.ptr[i] = buffer[length-i-1] - '0';
1259
1.40M
        }
1260
296k
    } else {
1261
296k
        uint64_t result = 0L;
1262
4.62M
        for (int32_t i = 0; i < length; i++) {
1263
4.32M
            result |= static_cast<uint64_t>(buffer[length-i-1] - '0') << (4 * i);
1264
4.32M
        }
1265
296k
        fBCD.bcdLong = result;
1266
296k
    }
1267
379k
    scale = point - length;
1268
379k
    precision = length;
1269
379k
}
1270
1271
1.38M
void DecimalQuantity::compact() {
1272
1.38M
    if (usingBytes) {
1273
252k
        int32_t delta = 0;
1274
299k
        for (; delta < precision && fBCD.bcdBytes.ptr[delta] == 0; delta++);
1275
252k
        if (delta == precision) {
1276
            // Number is zero
1277
0
            setBcdToZero();
1278
0
            return;
1279
252k
        } else {
1280
            // Remove trailing zeros
1281
252k
            shiftRight(delta);
1282
252k
        }
1283
1284
        // Compute precision
1285
252k
        int32_t leading = precision - 1;
1286
255k
        for (; leading >= 0 && fBCD.bcdBytes.ptr[leading] == 0; leading--);
1287
252k
        precision = leading + 1;
1288
1289
        // Switch storage mechanism if possible
1290
252k
        if (precision <= 16) {
1291
37.4k
            switchStorage();
1292
37.4k
        }
1293
1294
1.13M
    } else {
1295
1.13M
        if (fBCD.bcdLong == 0L) {
1296
            // Number is zero
1297
471k
            setBcdToZero();
1298
471k
            return;
1299
471k
        }
1300
1301
        // Compact the number (remove trailing zeros)
1302
        // TODO: Use a more efficient algorithm here and below. There is a logarithmic one.
1303
662k
        int32_t delta = 0;
1304
836k
        for (; delta < precision && getDigitPos(delta) == 0; delta++);
1305
662k
        fBCD.bcdLong >>= delta * 4;
1306
662k
        scale += delta;
1307
1308
        // Compute precision
1309
662k
        int32_t leading = precision - 1;
1310
845k
        for (; leading >= 0 && getDigitPos(leading) == 0; leading--);
1311
662k
        precision = leading + 1;
1312
662k
    }
1313
1.38M
}
1314
1315
285k
void DecimalQuantity::ensureCapacity() {
1316
285k
    ensureCapacity(40);
1317
285k
}
1318
1319
62.7M
void DecimalQuantity::ensureCapacity(int32_t capacity) {
1320
62.7M
    if (capacity == 0) { return; }
1321
62.7M
    int32_t oldCapacity = usingBytes ? fBCD.bcdBytes.len : 0;
1322
62.7M
    if (!usingBytes) {
1323
        // TODO: There is nothing being done to check for memory allocation failures.
1324
        // TODO: Consider indexing by nybbles instead of bytes in C++, so that we can
1325
        // make these arrays half the size.
1326
427k
        fBCD.bcdBytes.ptr = static_cast<int8_t*>(uprv_malloc(capacity * sizeof(int8_t)));
1327
427k
        fBCD.bcdBytes.len = capacity;
1328
        // Initialize the byte array to zeros (this is done automatically in Java)
1329
427k
        uprv_memset(fBCD.bcdBytes.ptr, 0, capacity * sizeof(int8_t));
1330
62.3M
    } else if (oldCapacity < capacity) {
1331
55.1k
        auto* bcd1 = static_cast<int8_t*>(uprv_malloc(capacity * 2 * sizeof(int8_t)));
1332
55.1k
        uprv_memcpy(bcd1, fBCD.bcdBytes.ptr, oldCapacity * sizeof(int8_t));
1333
        // Initialize the rest of the byte array to zeros (this is done automatically in Java)
1334
55.1k
        uprv_memset(bcd1 + oldCapacity, 0, (capacity - oldCapacity) * sizeof(int8_t));
1335
55.1k
        uprv_free(fBCD.bcdBytes.ptr);
1336
55.1k
        fBCD.bcdBytes.ptr = bcd1;
1337
55.1k
        fBCD.bcdBytes.len = capacity * 2;
1338
55.1k
    }
1339
62.7M
    usingBytes = true;
1340
62.7M
}
1341
1342
78.6k
void DecimalQuantity::switchStorage() {
1343
78.6k
    if (usingBytes) {
1344
        // Change from bytes to long
1345
37.4k
        uint64_t bcdLong = 0L;
1346
591k
        for (int i = precision - 1; i >= 0; i--) {
1347
553k
            bcdLong <<= 4;
1348
553k
            bcdLong |= fBCD.bcdBytes.ptr[i];
1349
553k
        }
1350
37.4k
        uprv_free(fBCD.bcdBytes.ptr);
1351
37.4k
        fBCD.bcdBytes.ptr = nullptr;
1352
37.4k
        fBCD.bcdLong = bcdLong;
1353
37.4k
        usingBytes = false;
1354
41.2k
    } else {
1355
        // Change from long to bytes
1356
        // Copy the long into a local variable since it will get munged when we allocate the bytes
1357
41.2k
        uint64_t bcdLong = fBCD.bcdLong;
1358
41.2k
        ensureCapacity();
1359
634k
        for (int i = 0; i < precision; i++) {
1360
593k
            fBCD.bcdBytes.ptr[i] = static_cast<int8_t>(bcdLong & 0xf);
1361
593k
            bcdLong >>= 4;
1362
593k
        }
1363
41.2k
        U_ASSERT(usingBytes);
1364
41.2k
    }
1365
78.6k
}
1366
1367
4.38M
void DecimalQuantity::copyBcdFrom(const DecimalQuantity &other) {
1368
4.38M
    setBcdToZero();
1369
4.38M
    if (other.usingBytes) {
1370
57.7k
        ensureCapacity(other.precision);
1371
57.7k
        uprv_memcpy(fBCD.bcdBytes.ptr, other.fBCD.bcdBytes.ptr, other.precision * sizeof(int8_t));
1372
4.32M
    } else {
1373
4.32M
        fBCD.bcdLong = other.fBCD.bcdLong;
1374
4.32M
    }
1375
4.38M
}
1376
1377
0
void DecimalQuantity::moveBcdFrom(DecimalQuantity &other) {
1378
0
    setBcdToZero();
1379
0
    if (other.usingBytes) {
1380
0
        usingBytes = true;
1381
0
        fBCD.bcdBytes.ptr = other.fBCD.bcdBytes.ptr;
1382
0
        fBCD.bcdBytes.len = other.fBCD.bcdBytes.len;
1383
        // Take ownership away from the old instance:
1384
0
        other.fBCD.bcdBytes.ptr = nullptr;
1385
0
        other.usingBytes = false;
1386
0
    } else {
1387
0
        fBCD.bcdLong = other.fBCD.bcdLong;
1388
0
    }
1389
0
}
1390
1391
0
const char16_t* DecimalQuantity::checkHealth() const {
1392
0
    if (usingBytes) {
1393
0
        if (precision == 0) { return u"Zero precision but we are in byte mode"; }
1394
0
        int32_t capacity = fBCD.bcdBytes.len;
1395
0
        if (precision > capacity) { return u"Precision exceeds length of byte array"; }
1396
0
        if (getDigitPos(precision - 1) == 0) { return u"Most significant digit is zero in byte mode"; }
1397
0
        if (getDigitPos(0) == 0) { return u"Least significant digit is zero in long mode"; }
1398
0
        for (int i = 0; i < precision; i++) {
1399
0
            if (getDigitPos(i) >= 10) { return u"Digit exceeding 10 in byte array"; }
1400
0
            if (getDigitPos(i) < 0) { return u"Digit below 0 in byte array"; }
1401
0
        }
1402
0
        for (int i = precision; i < capacity; i++) {
1403
0
            if (getDigitPos(i) != 0) { return u"Nonzero digits outside of range in byte array"; }
1404
0
        }
1405
0
    } else {
1406
0
        if (precision == 0 && fBCD.bcdLong != 0) {
1407
0
            return u"Value in bcdLong even though precision is zero";
1408
0
        }
1409
0
        if (precision > 16) { return u"Precision exceeds length of long"; }
1410
0
        if (precision != 0 && getDigitPos(precision - 1) == 0) {
1411
0
            return u"Most significant digit is zero in long mode";
1412
0
        }
1413
0
        if (precision != 0 && getDigitPos(0) == 0) {
1414
0
            return u"Least significant digit is zero in long mode";
1415
0
        }
1416
0
        for (int i = 0; i < precision; i++) {
1417
0
            if (getDigitPos(i) >= 10) { return u"Digit exceeding 10 in long"; }
1418
0
            if (getDigitPos(i) < 0) { return u"Digit below 0 in long (?!)"; }
1419
0
        }
1420
0
        for (int i = precision; i < 16; i++) {
1421
0
            if (getDigitPos(i) != 0) { return u"Nonzero digits outside of range in long"; }
1422
0
        }
1423
0
    }
1424
1425
    // No error
1426
0
    return nullptr;
1427
0
}
1428
1429
0
bool DecimalQuantity::operator==(const DecimalQuantity& other) const {
1430
0
    bool basicEquals =
1431
0
            scale == other.scale
1432
0
            && precision == other.precision
1433
0
            && flags == other.flags
1434
0
            && lReqPos == other.lReqPos
1435
0
            && rReqPos == other.rReqPos
1436
0
            && isApproximate == other.isApproximate;
1437
0
    if (!basicEquals) {
1438
0
        return false;
1439
0
    }
1440
1441
0
    if (precision == 0) {
1442
0
        return true;
1443
0
    } else if (isApproximate) {
1444
0
        return origDouble == other.origDouble && origDelta == other.origDelta;
1445
0
    } else {
1446
0
        for (int m = getUpperDisplayMagnitude(); m >= getLowerDisplayMagnitude(); m--) {
1447
0
            if (getDigit(m) != other.getDigit(m)) {
1448
0
                return false;
1449
0
            }
1450
0
        }
1451
0
        return true;
1452
0
    }
1453
0
}
1454
1455
0
UnicodeString DecimalQuantity::toString() const {
1456
0
    UErrorCode localStatus = U_ZERO_ERROR;
1457
0
    MaybeStackArray<char, 30> digits(precision + 1, localStatus);
1458
0
    if (U_FAILURE(localStatus)) {
1459
0
        return ICU_Utility::makeBogusString();
1460
0
    }
1461
0
    for (int32_t i = 0; i < precision; i++) {
1462
0
        digits[i] = getDigitPos(precision - i - 1) + '0';
1463
0
    }
1464
0
    digits[precision] = 0; // terminate buffer
1465
0
    char buffer8[100];
1466
0
    snprintf(
1467
0
            buffer8,
1468
0
            sizeof(buffer8),
1469
0
            "<DecimalQuantity %d:%d %s %s%s%s%d>",
1470
0
            lReqPos,
1471
0
            rReqPos,
1472
0
            (usingBytes ? "bytes" : "long"),
1473
0
            (isNegative() ? "-" : ""),
1474
0
            (precision == 0 ? "0" : digits.getAlias()),
1475
0
            "E",
1476
0
            scale);
1477
0
    return UnicodeString(buffer8, -1, US_INV);
1478
0
}
1479
1480
#endif /* #if !UCONFIG_NO_FORMATTING */