tor-browser

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

number_decimalquantity.cpp (47527B)


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