Home | History | Annotate | Download | only in i18n
      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 && !UPRV_INCOMPLETE_CPP11_SUPPORT
      7 
      8 #include "uassert.h"
      9 #include <cmath>
     10 #include "cmemory.h"
     11 #include "decNumber.h"
     12 #include <limits>
     13 #include "number_decimalquantity.h"
     14 #include "decContext.h"
     15 #include "decNumber.h"
     16 #include "number_roundingutils.h"
     17 #include "unicode/plurrule.h"
     18 
     19 using namespace icu;
     20 using namespace icu::number;
     21 using namespace icu::number::impl;
     22 
     23 namespace {
     24 
     25 int8_t NEGATIVE_FLAG = 1;
     26 int8_t INFINITY_FLAG = 2;
     27 int8_t NAN_FLAG = 4;
     28 
     29 static constexpr int32_t DEFAULT_DIGITS = 34;
     30 typedef MaybeStackHeaderAndArray<decNumber, char, DEFAULT_DIGITS> DecNumberWithStorage;
     31 
     32 /** Helper function to convert a decNumber-compatible string into a decNumber. */
     33 void stringToDecNumber(StringPiece n, DecNumberWithStorage &dn) {
     34     decContext set;
     35     uprv_decContextDefault(&set, DEC_INIT_BASE);
     36     uprv_decContextSetRounding(&set, DEC_ROUND_HALF_EVEN);
     37     set.traps = 0; // no traps, thank you
     38     if (n.length() > DEFAULT_DIGITS) {
     39         dn.resize(n.length(), 0);
     40         set.digits = n.length();
     41     } else {
     42         set.digits = DEFAULT_DIGITS;
     43     }
     44     uprv_decNumberFromString(dn.getAlias(), n.data(), &set);
     45     U_ASSERT(DECDPUN == 1);
     46 }
     47 
     48 /** Helper function for safe subtraction (no overflow). */
     49 inline int32_t safeSubtract(int32_t a, int32_t b) {
     50     // Note: In C++, signed integer subtraction is undefined behavior.
     51     int32_t diff = static_cast<int32_t>(static_cast<uint32_t>(a) - static_cast<uint32_t>(b));
     52     if (b < 0 && diff < a) { return INT32_MAX; }
     53     if (b > 0 && diff > a) { return INT32_MIN; }
     54     return diff;
     55 }
     56 
     57 static double DOUBLE_MULTIPLIERS[] = {
     58         1e0,
     59         1e1,
     60         1e2,
     61         1e3,
     62         1e4,
     63         1e5,
     64         1e6,
     65         1e7,
     66         1e8,
     67         1e9,
     68         1e10,
     69         1e11,
     70         1e12,
     71         1e13,
     72         1e14,
     73         1e15,
     74         1e16,
     75         1e17,
     76         1e18,
     77         1e19,
     78         1e20,
     79         1e21};
     80 
     81 }  // namespace
     82 
     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::operator=(const DecimalQuantity &other) {
    102     if (this == &other) {
    103         return *this;
    104     }
    105     copyBcdFrom(other);
    106     lOptPos = other.lOptPos;
    107     lReqPos = other.lReqPos;
    108     rReqPos = other.rReqPos;
    109     rOptPos = other.rOptPos;
    110     scale = other.scale;
    111     precision = other.precision;
    112     flags = other.flags;
    113     origDouble = other.origDouble;
    114     origDelta = other.origDelta;
    115     isApproximate = other.isApproximate;
    116     return *this;
    117 }
    118 
    119 void DecimalQuantity::clear() {
    120     lOptPos = INT32_MAX;
    121     lReqPos = 0;
    122     rReqPos = 0;
    123     rOptPos = INT32_MIN;
    124     flags = 0;
    125     setBcdToZero(); // sets scale, precision, hasDouble, origDouble, origDelta, and BCD data
    126 }
    127 
    128 void DecimalQuantity::setIntegerLength(int32_t minInt, int32_t maxInt) {
    129     // Validation should happen outside of DecimalQuantity, e.g., in the Rounder class.
    130     U_ASSERT(minInt >= 0);
    131     U_ASSERT(maxInt >= minInt);
    132 
    133     // Save values into internal state
    134     // Negation is safe for minFrac/maxFrac because -Integer.MAX_VALUE > Integer.MIN_VALUE
    135     lOptPos = maxInt;
    136     lReqPos = minInt;
    137 }
    138 
    139 void DecimalQuantity::setFractionLength(int32_t minFrac, int32_t maxFrac) {
    140     // Validation should happen outside of DecimalQuantity, e.g., in the Rounder class.
    141     U_ASSERT(minFrac >= 0);
    142     U_ASSERT(maxFrac >= minFrac);
    143 
    144     // Save values into internal state
    145     // Negation is safe for minFrac/maxFrac because -Integer.MAX_VALUE > Integer.MIN_VALUE
    146     rReqPos = -minFrac;
    147     rOptPos = -maxFrac;
    148 }
    149 
    150 uint64_t DecimalQuantity::getPositionFingerprint() const {
    151     uint64_t fingerprint = 0;
    152     fingerprint ^= lOptPos;
    153     fingerprint ^= (lReqPos << 16);
    154     fingerprint ^= (static_cast<uint64_t>(rReqPos) << 32);
    155     fingerprint ^= (static_cast<uint64_t>(rOptPos) << 48);
    156     return fingerprint;
    157 }
    158 
    159 void DecimalQuantity::roundToIncrement(double roundingIncrement, RoundingMode roundingMode,
    160                                        int32_t minMaxFrac, UErrorCode& status) {
    161     // TODO: This is innefficient.  Improve?
    162     // TODO: Should we convert to decNumber instead?
    163     double temp = toDouble();
    164     temp /= roundingIncrement;
    165     setToDouble(temp);
    166     roundToMagnitude(0, roundingMode, status);
    167     temp = toDouble();
    168     temp *= roundingIncrement;
    169     setToDouble(temp);
    170     // Since we reset the value to a double, we need to specify the rounding boundary
    171     // in order to get the DecimalQuantity out of approximation mode.
    172     roundToMagnitude(-minMaxFrac, roundingMode, status);
    173 }
    174 
    175 void DecimalQuantity::multiplyBy(int32_t multiplicand) {
    176     if (isInfinite() || isZero() || isNaN()) {
    177         return;
    178     }
    179     // TODO: Should we convert to decNumber instead?
    180     double temp = toDouble();
    181     temp *= multiplicand;
    182     setToDouble(temp);
    183 }
    184 
    185 int32_t DecimalQuantity::getMagnitude() const {
    186     U_ASSERT(precision != 0);
    187     return scale + precision - 1;
    188 }
    189 
    190 void DecimalQuantity::adjustMagnitude(int32_t delta) {
    191     if (precision != 0) {
    192         scale += delta;
    193         origDelta += delta;
    194     }
    195 }
    196 
    197 StandardPlural::Form DecimalQuantity::getStandardPlural(const PluralRules *rules) const {
    198     if (rules == nullptr) {
    199         // Fail gracefully if the user didn't provide a PluralRules
    200         return StandardPlural::Form::OTHER;
    201     } else {
    202         UnicodeString ruleString = rules->select(*this);
    203         return StandardPlural::orOtherFromString(ruleString);
    204     }
    205 }
    206 
    207 double DecimalQuantity::getPluralOperand(PluralOperand operand) const {
    208     // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
    209     // See the comment at the top of this file explaining the "isApproximate" field.
    210     U_ASSERT(!isApproximate);
    211 
    212     switch (operand) {
    213         case PLURAL_OPERAND_I:
    214             return static_cast<double>(toLong());
    215         case PLURAL_OPERAND_F:
    216             return static_cast<double>(toFractionLong(true));
    217         case PLURAL_OPERAND_T:
    218             return static_cast<double>(toFractionLong(false));
    219         case PLURAL_OPERAND_V:
    220             return fractionCount();
    221         case PLURAL_OPERAND_W:
    222             return fractionCountWithoutTrailingZeros();
    223         default:
    224             return std::abs(toDouble());
    225     }
    226 }
    227 
    228 int32_t DecimalQuantity::getUpperDisplayMagnitude() const {
    229     // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
    230     // See the comment in the header file explaining the "isApproximate" field.
    231     U_ASSERT(!isApproximate);
    232 
    233     int32_t magnitude = scale + precision;
    234     int32_t result = (lReqPos > magnitude) ? lReqPos : (lOptPos < magnitude) ? lOptPos : magnitude;
    235     return result - 1;
    236 }
    237 
    238 int32_t DecimalQuantity::getLowerDisplayMagnitude() const {
    239     // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
    240     // See the comment in the header file explaining the "isApproximate" field.
    241     U_ASSERT(!isApproximate);
    242 
    243     int32_t magnitude = scale;
    244     int32_t result = (rReqPos < magnitude) ? rReqPos : (rOptPos > magnitude) ? rOptPos : magnitude;
    245     return result;
    246 }
    247 
    248 int8_t DecimalQuantity::getDigit(int32_t magnitude) const {
    249     // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
    250     // See the comment at the top of this file explaining the "isApproximate" field.
    251     U_ASSERT(!isApproximate);
    252 
    253     return getDigitPos(magnitude - scale);
    254 }
    255 
    256 int32_t DecimalQuantity::fractionCount() const {
    257     return -getLowerDisplayMagnitude();
    258 }
    259 
    260 int32_t DecimalQuantity::fractionCountWithoutTrailingZeros() const {
    261     return -scale > 0 ? -scale : 0;  // max(-scale, 0)
    262 }
    263 
    264 bool DecimalQuantity::isNegative() const {
    265     return (flags & NEGATIVE_FLAG) != 0;
    266 }
    267 
    268 bool DecimalQuantity::isInfinite() const {
    269     return (flags & INFINITY_FLAG) != 0;
    270 }
    271 
    272 bool DecimalQuantity::isNaN() const {
    273     return (flags & NAN_FLAG) != 0;
    274 }
    275 
    276 bool DecimalQuantity::isZero() const {
    277     return precision == 0;
    278 }
    279 
    280 DecimalQuantity &DecimalQuantity::setToInt(int32_t n) {
    281     setBcdToZero();
    282     flags = 0;
    283     if (n < 0) {
    284         flags |= NEGATIVE_FLAG;
    285         n = -n;
    286     }
    287     if (n != 0) {
    288         _setToInt(n);
    289         compact();
    290     }
    291     return *this;
    292 }
    293 
    294 void DecimalQuantity::_setToInt(int32_t n) {
    295     if (n == INT32_MIN) {
    296         readLongToBcd(-static_cast<int64_t>(n));
    297     } else {
    298         readIntToBcd(n);
    299     }
    300 }
    301 
    302 DecimalQuantity &DecimalQuantity::setToLong(int64_t n) {
    303     setBcdToZero();
    304     flags = 0;
    305     if (n < 0) {
    306         flags |= NEGATIVE_FLAG;
    307         n = -n;
    308     }
    309     if (n != 0) {
    310         _setToLong(n);
    311         compact();
    312     }
    313     return *this;
    314 }
    315 
    316 void DecimalQuantity::_setToLong(int64_t n) {
    317     if (n == INT64_MIN) {
    318         static const char *int64minStr = "9.223372036854775808E+18";
    319         DecNumberWithStorage dn;
    320         stringToDecNumber(int64minStr, dn);
    321         readDecNumberToBcd(dn.getAlias());
    322     } else if (n <= INT32_MAX) {
    323         readIntToBcd(static_cast<int32_t>(n));
    324     } else {
    325         readLongToBcd(n);
    326     }
    327 }
    328 
    329 DecimalQuantity &DecimalQuantity::setToDouble(double n) {
    330     setBcdToZero();
    331     flags = 0;
    332     // signbit() from <math.h> handles +0.0 vs -0.0
    333     if (std::signbit(n) != 0) {
    334         flags |= NEGATIVE_FLAG;
    335         n = -n;
    336     }
    337     if (std::isnan(n) != 0) {
    338         flags |= NAN_FLAG;
    339     } else if (std::isfinite(n) == 0) {
    340         flags |= INFINITY_FLAG;
    341     } else if (n != 0) {
    342         _setToDoubleFast(n);
    343         compact();
    344     }
    345     return *this;
    346 }
    347 
    348 void DecimalQuantity::_setToDoubleFast(double n) {
    349     isApproximate = true;
    350     origDouble = n;
    351     origDelta = 0;
    352 
    353     // Make sure the double is an IEEE 754 double.  If not, fall back to the slow path right now.
    354     // TODO: Make a fast path for other types of doubles.
    355     if (!std::numeric_limits<double>::is_iec559) {
    356         convertToAccurateDouble();
    357         // Turn off the approximate double flag, since the value is now exact.
    358         isApproximate = false;
    359         origDouble = 0.0;
    360         return;
    361     }
    362 
    363     // To get the bits from the double, use memcpy, which takes care of endianness.
    364     uint64_t ieeeBits;
    365     uprv_memcpy(&ieeeBits, &n, sizeof(n));
    366     int32_t exponent = static_cast<int32_t>((ieeeBits & 0x7ff0000000000000L) >> 52) - 0x3ff;
    367 
    368     // Not all integers can be represented exactly for exponent > 52
    369     if (exponent <= 52 && static_cast<int64_t>(n) == n) {
    370         _setToLong(static_cast<int64_t>(n));
    371         return;
    372     }
    373 
    374     // 3.3219... is log2(10)
    375     auto fracLength = static_cast<int32_t> ((52 - exponent) / 3.32192809489);
    376     if (fracLength >= 0) {
    377         int32_t i = fracLength;
    378         // 1e22 is the largest exact double.
    379         for (; i >= 22; i -= 22) n *= 1e22;
    380         n *= DOUBLE_MULTIPLIERS[i];
    381     } else {
    382         int32_t i = fracLength;
    383         // 1e22 is the largest exact double.
    384         for (; i <= -22; i += 22) n /= 1e22;
    385         n /= DOUBLE_MULTIPLIERS[-i];
    386     }
    387     auto result = static_cast<int64_t>(std::round(n));
    388     if (result != 0) {
    389         _setToLong(result);
    390         scale -= fracLength;
    391     }
    392 }
    393 
    394 void DecimalQuantity::convertToAccurateDouble() {
    395     double n = origDouble;
    396     U_ASSERT(n != 0);
    397     int32_t delta = origDelta;
    398     setBcdToZero();
    399 
    400     // Call the slow oracle function (Double.toString in Java, sprintf in C++).
    401     // The <float.h> constant DBL_DIG defines a platform-specific number of digits in a double.
    402     // However, this tends to be too low (see #11318). Instead, we always use 14 decimal places.
    403     static constexpr size_t CAP = 1 + 14 + 8; // Extra space for '+', '.', e+NNN, and '\0'
    404     char dstr[CAP];
    405     snprintf(dstr, CAP, "%+1.14e", n);
    406 
    407     // uprv_decNumberFromString() will parse the string expecting '.' as a
    408     // decimal separator, however sprintf() can use ',' in certain locales.
    409     // Overwrite a ',' with '.' here before proceeding.
    410     char *decimalSeparator = strchr(dstr, ',');
    411     if (decimalSeparator != nullptr) {
    412         *decimalSeparator = '.';
    413     }
    414 
    415     StringPiece sp(dstr);
    416     DecNumberWithStorage dn;
    417     stringToDecNumber(dstr, dn);
    418     _setToDecNumber(dn.getAlias());
    419 
    420     scale += delta;
    421     explicitExactDouble = true;
    422 }
    423 
    424 DecimalQuantity &DecimalQuantity::setToDecNumber(StringPiece n) {
    425     setBcdToZero();
    426     flags = 0;
    427 
    428     DecNumberWithStorage dn;
    429     stringToDecNumber(n, dn);
    430 
    431     // The code path for decNumber is modeled after BigDecimal in Java.
    432     if (decNumberIsNegative(dn.getAlias())) {
    433         flags |= NEGATIVE_FLAG;
    434     }
    435     if (!decNumberIsZero(dn.getAlias())) {
    436         _setToDecNumber(dn.getAlias());
    437     }
    438     return *this;
    439 }
    440 
    441 void DecimalQuantity::_setToDecNumber(decNumber *n) {
    442     // Java fastpaths for ints here. In C++, just always read directly from the decNumber.
    443     readDecNumberToBcd(n);
    444     compact();
    445 }
    446 
    447 int64_t DecimalQuantity::toLong() const {
    448     int64_t result = 0L;
    449     for (int32_t magnitude = scale + precision - 1; magnitude >= 0; magnitude--) {
    450         result = result * 10 + getDigitPos(magnitude - scale);
    451     }
    452     return result;
    453 }
    454 
    455 int64_t DecimalQuantity::toFractionLong(bool includeTrailingZeros) const {
    456     int64_t result = 0L;
    457     int32_t magnitude = -1;
    458     for (; (magnitude >= scale || (includeTrailingZeros && magnitude >= rReqPos)) &&
    459            magnitude >= rOptPos; magnitude--) {
    460         result = result * 10 + getDigitPos(magnitude - scale);
    461     }
    462     return result;
    463 }
    464 
    465 double DecimalQuantity::toDouble() const {
    466     if (isApproximate) {
    467         return toDoubleFromOriginal();
    468     }
    469 
    470     if (isNaN()) {
    471         return NAN;
    472     } else if (isInfinite()) {
    473         return isNegative() ? -INFINITY : INFINITY;
    474     }
    475 
    476     int64_t tempLong = 0L;
    477     int32_t lostDigits = precision - (precision < 17 ? precision : 17);
    478     for (int shift = precision - 1; shift >= lostDigits; shift--) {
    479         tempLong = tempLong * 10 + getDigitPos(shift);
    480     }
    481     double result = static_cast<double>(tempLong);
    482     int32_t _scale = scale + lostDigits;
    483     if (_scale >= 0) {
    484         // 1e22 is the largest exact double.
    485         int32_t i = _scale;
    486         for (; i >= 22; i -= 22) result *= 1e22;
    487         result *= DOUBLE_MULTIPLIERS[i];
    488     } else {
    489         // 1e22 is the largest exact double.
    490         int32_t i = _scale;
    491         for (; i <= -22; i += 22) result /= 1e22;
    492         result /= DOUBLE_MULTIPLIERS[-i];
    493     }
    494     if (isNegative()) { result = -result; }
    495     return result;
    496 }
    497 
    498 double DecimalQuantity::toDoubleFromOriginal() const {
    499     double result = origDouble;
    500     int32_t delta = origDelta;
    501     if (delta >= 0) {
    502         // 1e22 is the largest exact double.
    503         for (; delta >= 22; delta -= 22) result *= 1e22;
    504         result *= DOUBLE_MULTIPLIERS[delta];
    505     } else {
    506         // 1e22 is the largest exact double.
    507         for (; delta <= -22; delta += 22) result /= 1e22;
    508         result /= DOUBLE_MULTIPLIERS[-delta];
    509     }
    510     if (isNegative()) { result *= -1; }
    511     return result;
    512 }
    513 
    514 void DecimalQuantity::roundToMagnitude(int32_t magnitude, RoundingMode roundingMode, UErrorCode& status) {
    515     // The position in the BCD at which rounding will be performed; digits to the right of position
    516     // will be rounded away.
    517     // TODO: Andy: There was a test failure because of integer overflow here. Should I do
    518     // "safe subtraction" everywhere in the code?  What's the nicest way to do it?
    519     int position = safeSubtract(magnitude, scale);
    520 
    521     if (position <= 0 && !isApproximate) {
    522         // All digits are to the left of the rounding magnitude.
    523     } else if (precision == 0) {
    524         // No rounding for zero.
    525     } else {
    526         // Perform rounding logic.
    527         // "leading" = most significant digit to the right of rounding
    528         // "trailing" = least significant digit to the left of rounding
    529         int8_t leadingDigit = getDigitPos(safeSubtract(position, 1));
    530         int8_t trailingDigit = getDigitPos(position);
    531 
    532         // Compute which section of the number we are in.
    533         // EDGE means we are at the bottom or top edge, like 1.000 or 1.999 (used by doubles)
    534         // LOWER means we are between the bottom edge and the midpoint, like 1.391
    535         // MIDPOINT means we are exactly in the middle, like 1.500
    536         // UPPER means we are between the midpoint and the top edge, like 1.916
    537         roundingutils::Section section = roundingutils::SECTION_MIDPOINT;
    538         if (!isApproximate) {
    539             if (leadingDigit < 5) {
    540                 section = roundingutils::SECTION_LOWER;
    541             } else if (leadingDigit > 5) {
    542                 section = roundingutils::SECTION_UPPER;
    543             } else {
    544                 for (int p = safeSubtract(position, 2); p >= 0; p--) {
    545                     if (getDigitPos(p) != 0) {
    546                         section = roundingutils::SECTION_UPPER;
    547                         break;
    548                     }
    549                 }
    550             }
    551         } else {
    552             int32_t p = safeSubtract(position, 2);
    553             int32_t minP = uprv_max(0, precision - 14);
    554             if (leadingDigit == 0) {
    555                 section = roundingutils::SECTION_LOWER_EDGE;
    556                 for (; p >= minP; p--) {
    557                     if (getDigitPos(p) != 0) {
    558                         section = roundingutils::SECTION_LOWER;
    559                         break;
    560                     }
    561                 }
    562             } else if (leadingDigit == 4) {
    563                 for (; p >= minP; p--) {
    564                     if (getDigitPos(p) != 9) {
    565                         section = roundingutils::SECTION_LOWER;
    566                         break;
    567                     }
    568                 }
    569             } else if (leadingDigit == 5) {
    570                 for (; p >= minP; p--) {
    571                     if (getDigitPos(p) != 0) {
    572                         section = roundingutils::SECTION_UPPER;
    573                         break;
    574                     }
    575                 }
    576             } else if (leadingDigit == 9) {
    577                 section = roundingutils::SECTION_UPPER_EDGE;
    578                 for (; p >= minP; p--) {
    579                     if (getDigitPos(p) != 9) {
    580                         section = roundingutils::SECTION_UPPER;
    581                         break;
    582                     }
    583                 }
    584             } else if (leadingDigit < 5) {
    585                 section = roundingutils::SECTION_LOWER;
    586             } else {
    587                 section = roundingutils::SECTION_UPPER;
    588             }
    589 
    590             bool roundsAtMidpoint = roundingutils::roundsAtMidpoint(roundingMode);
    591             if (safeSubtract(position, 1) < precision - 14 ||
    592                 (roundsAtMidpoint && section == roundingutils::SECTION_MIDPOINT) ||
    593                 (!roundsAtMidpoint && section < 0 /* i.e. at upper or lower edge */)) {
    594                 // Oops! This means that we have to get the exact representation of the double, because
    595                 // the zone of uncertainty is along the rounding boundary.
    596                 convertToAccurateDouble();
    597                 roundToMagnitude(magnitude, roundingMode, status); // start over
    598                 return;
    599             }
    600 
    601             // Turn off the approximate double flag, since the value is now confirmed to be exact.
    602             isApproximate = false;
    603             origDouble = 0.0;
    604             origDelta = 0;
    605 
    606             if (position <= 0) {
    607                 // All digits are to the left of the rounding magnitude.
    608                 return;
    609             }
    610 
    611             // Good to continue rounding.
    612             if (section == -1) { section = roundingutils::SECTION_LOWER; }
    613             if (section == -2) { section = roundingutils::SECTION_UPPER; }
    614         }
    615 
    616         bool roundDown = roundingutils::getRoundingDirection((trailingDigit % 2) == 0,
    617                 isNegative(),
    618                 section,
    619                 roundingMode,
    620                 status);
    621         if (U_FAILURE(status)) {
    622             return;
    623         }
    624 
    625         // Perform truncation
    626         if (position >= precision) {
    627             setBcdToZero();
    628             scale = magnitude;
    629         } else {
    630             shiftRight(position);
    631         }
    632 
    633         // Bubble the result to the higher digits
    634         if (!roundDown) {
    635             if (trailingDigit == 9) {
    636                 int bubblePos = 0;
    637                 // Note: in the long implementation, the most digits BCD can have at this point is 15,
    638                 // so bubblePos <= 15 and getDigitPos(bubblePos) is safe.
    639                 for (; getDigitPos(bubblePos) == 9; bubblePos++) {}
    640                 shiftRight(bubblePos); // shift off the trailing 9s
    641             }
    642             int8_t digit0 = getDigitPos(0);
    643             U_ASSERT(digit0 != 9);
    644             setDigitPos(0, static_cast<int8_t>(digit0 + 1));
    645             precision += 1; // in case an extra digit got added
    646         }
    647 
    648         compact();
    649     }
    650 }
    651 
    652 void DecimalQuantity::roundToInfinity() {
    653     if (isApproximate) {
    654         convertToAccurateDouble();
    655     }
    656 }
    657 
    658 void DecimalQuantity::appendDigit(int8_t value, int32_t leadingZeros, bool appendAsInteger) {
    659     U_ASSERT(leadingZeros >= 0);
    660 
    661     // Zero requires special handling to maintain the invariant that the least-significant digit
    662     // in the BCD is nonzero.
    663     if (value == 0) {
    664         if (appendAsInteger && precision != 0) {
    665             scale += leadingZeros + 1;
    666         }
    667         return;
    668     }
    669 
    670     // Deal with trailing zeros
    671     if (scale > 0) {
    672         leadingZeros += scale;
    673         if (appendAsInteger) {
    674             scale = 0;
    675         }
    676     }
    677 
    678     // Append digit
    679     shiftLeft(leadingZeros + 1);
    680     setDigitPos(0, value);
    681 
    682     // Fix scale if in integer mode
    683     if (appendAsInteger) {
    684         scale += leadingZeros + 1;
    685     }
    686 }
    687 
    688 UnicodeString DecimalQuantity::toPlainString() const {
    689     UnicodeString sb;
    690     if (isNegative()) {
    691         sb.append(u'-');
    692     }
    693     for (int m = getUpperDisplayMagnitude(); m >= getLowerDisplayMagnitude(); m--) {
    694         sb.append(getDigit(m) + u'0');
    695         if (m == 0) { sb.append(u'.'); }
    696     }
    697     return sb;
    698 }
    699 
    700 ////////////////////////////////////////////////////
    701 /// End of DecimalQuantity_AbstractBCD.java      ///
    702 /// Start of DecimalQuantity_DualStorageBCD.java ///
    703 ////////////////////////////////////////////////////
    704 
    705 int8_t DecimalQuantity::getDigitPos(int32_t position) const {
    706     if (usingBytes) {
    707         if (position < 0 || position > precision) { return 0; }
    708         return fBCD.bcdBytes.ptr[position];
    709     } else {
    710         if (position < 0 || position >= 16) { return 0; }
    711         return (int8_t) ((fBCD.bcdLong >> (position * 4)) & 0xf);
    712     }
    713 }
    714 
    715 void DecimalQuantity::setDigitPos(int32_t position, int8_t value) {
    716     U_ASSERT(position >= 0);
    717     if (usingBytes) {
    718         ensureCapacity(position + 1);
    719         fBCD.bcdBytes.ptr[position] = value;
    720     } else if (position >= 16) {
    721         switchStorage();
    722         ensureCapacity(position + 1);
    723         fBCD.bcdBytes.ptr[position] = value;
    724     } else {
    725         int shift = position * 4;
    726         fBCD.bcdLong = (fBCD.bcdLong & ~(0xfL << shift)) | ((long) value << shift);
    727     }
    728 }
    729 
    730 void DecimalQuantity::shiftLeft(int32_t numDigits) {
    731     if (!usingBytes && precision + numDigits > 16) {
    732         switchStorage();
    733     }
    734     if (usingBytes) {
    735         ensureCapacity(precision + numDigits);
    736         int i = precision + numDigits - 1;
    737         for (; i >= numDigits; i--) {
    738             fBCD.bcdBytes.ptr[i] = fBCD.bcdBytes.ptr[i - numDigits];
    739         }
    740         for (; i >= 0; i--) {
    741             fBCD.bcdBytes.ptr[i] = 0;
    742         }
    743     } else {
    744         fBCD.bcdLong <<= (numDigits * 4);
    745     }
    746     scale -= numDigits;
    747     precision += numDigits;
    748 }
    749 
    750 void DecimalQuantity::shiftRight(int32_t numDigits) {
    751     if (usingBytes) {
    752         int i = 0;
    753         for (; i < precision - numDigits; i++) {
    754             fBCD.bcdBytes.ptr[i] = fBCD.bcdBytes.ptr[i + numDigits];
    755         }
    756         for (; i < precision; i++) {
    757             fBCD.bcdBytes.ptr[i] = 0;
    758         }
    759     } else {
    760         fBCD.bcdLong >>= (numDigits * 4);
    761     }
    762     scale += numDigits;
    763     precision -= numDigits;
    764 }
    765 
    766 void DecimalQuantity::setBcdToZero() {
    767     if (usingBytes) {
    768         uprv_free(fBCD.bcdBytes.ptr);
    769         fBCD.bcdBytes.ptr = nullptr;
    770         usingBytes = false;
    771     }
    772     fBCD.bcdLong = 0L;
    773     scale = 0;
    774     precision = 0;
    775     isApproximate = false;
    776     origDouble = 0;
    777     origDelta = 0;
    778 }
    779 
    780 void DecimalQuantity::readIntToBcd(int32_t n) {
    781     U_ASSERT(n != 0);
    782     // ints always fit inside the long implementation.
    783     uint64_t result = 0L;
    784     int i = 16;
    785     for (; n != 0; n /= 10, i--) {
    786         result = (result >> 4) + ((static_cast<uint64_t>(n) % 10) << 60);
    787     }
    788     U_ASSERT(!usingBytes);
    789     fBCD.bcdLong = result >> (i * 4);
    790     scale = 0;
    791     precision = 16 - i;
    792 }
    793 
    794 void DecimalQuantity::readLongToBcd(int64_t n) {
    795     U_ASSERT(n != 0);
    796     if (n >= 10000000000000000L) {
    797         ensureCapacity();
    798         int i = 0;
    799         for (; n != 0L; n /= 10L, i++) {
    800             fBCD.bcdBytes.ptr[i] = static_cast<int8_t>(n % 10);
    801         }
    802         U_ASSERT(usingBytes);
    803         scale = 0;
    804         precision = i;
    805     } else {
    806         uint64_t result = 0L;
    807         int i = 16;
    808         for (; n != 0L; n /= 10L, i--) {
    809             result = (result >> 4) + ((n % 10) << 60);
    810         }
    811         U_ASSERT(i >= 0);
    812         U_ASSERT(!usingBytes);
    813         fBCD.bcdLong = result >> (i * 4);
    814         scale = 0;
    815         precision = 16 - i;
    816     }
    817 }
    818 
    819 void DecimalQuantity::readDecNumberToBcd(decNumber *dn) {
    820     if (dn->digits > 16) {
    821         ensureCapacity(dn->digits);
    822         for (int32_t i = 0; i < dn->digits; i++) {
    823             fBCD.bcdBytes.ptr[i] = dn->lsu[i];
    824         }
    825     } else {
    826         uint64_t result = 0L;
    827         for (int32_t i = 0; i < dn->digits; i++) {
    828             result |= static_cast<uint64_t>(dn->lsu[i]) << (4 * i);
    829         }
    830         fBCD.bcdLong = result;
    831     }
    832     scale = dn->exponent;
    833     precision = dn->digits;
    834 }
    835 
    836 void DecimalQuantity::compact() {
    837     if (usingBytes) {
    838         int32_t delta = 0;
    839         for (; delta < precision && fBCD.bcdBytes.ptr[delta] == 0; delta++);
    840         if (delta == precision) {
    841             // Number is zero
    842             setBcdToZero();
    843             return;
    844         } else {
    845             // Remove trailing zeros
    846             shiftRight(delta);
    847         }
    848 
    849         // Compute precision
    850         int32_t leading = precision - 1;
    851         for (; leading >= 0 && fBCD.bcdBytes.ptr[leading] == 0; leading--);
    852         precision = leading + 1;
    853 
    854         // Switch storage mechanism if possible
    855         if (precision <= 16) {
    856             switchStorage();
    857         }
    858 
    859     } else {
    860         if (fBCD.bcdLong == 0L) {
    861             // Number is zero
    862             setBcdToZero();
    863             return;
    864         }
    865 
    866         // Compact the number (remove trailing zeros)
    867         // TODO: Use a more efficient algorithm here and below. There is a logarithmic one.
    868         int32_t delta = 0;
    869         for (; delta < precision && getDigitPos(delta) == 0; delta++);
    870         fBCD.bcdLong >>= delta * 4;
    871         scale += delta;
    872 
    873         // Compute precision
    874         int32_t leading = precision - 1;
    875         for (; leading >= 0 && getDigitPos(leading) == 0; leading--);
    876         precision = leading + 1;
    877     }
    878 }
    879 
    880 void DecimalQuantity::ensureCapacity() {
    881     ensureCapacity(40);
    882 }
    883 
    884 void DecimalQuantity::ensureCapacity(int32_t capacity) {
    885     if (capacity == 0) { return; }
    886     int32_t oldCapacity = usingBytes ? fBCD.bcdBytes.len : 0;
    887     if (!usingBytes) {
    888         // TODO: There is nothing being done to check for memory allocation failures.
    889         // TODO: Consider indexing by nybbles instead of bytes in C++, so that we can
    890         // make these arrays half the size.
    891         fBCD.bcdBytes.ptr = static_cast<int8_t*>(uprv_malloc(capacity * sizeof(int8_t)));
    892         fBCD.bcdBytes.len = capacity;
    893         // Initialize the byte array to zeros (this is done automatically in Java)
    894         uprv_memset(fBCD.bcdBytes.ptr, 0, capacity * sizeof(int8_t));
    895     } else if (oldCapacity < capacity) {
    896         auto bcd1 = static_cast<int8_t*>(uprv_malloc(capacity * 2 * sizeof(int8_t)));
    897         uprv_memcpy(bcd1, fBCD.bcdBytes.ptr, oldCapacity * sizeof(int8_t));
    898         // Initialize the rest of the byte array to zeros (this is done automatically in Java)
    899         uprv_memset(fBCD.bcdBytes.ptr + oldCapacity, 0, (capacity - oldCapacity) * sizeof(int8_t));
    900         uprv_free(fBCD.bcdBytes.ptr);
    901         fBCD.bcdBytes.ptr = bcd1;
    902         fBCD.bcdBytes.len = capacity * 2;
    903     }
    904     usingBytes = true;
    905 }
    906 
    907 void DecimalQuantity::switchStorage() {
    908     if (usingBytes) {
    909         // Change from bytes to long
    910         uint64_t bcdLong = 0L;
    911         for (int i = precision - 1; i >= 0; i--) {
    912             bcdLong <<= 4;
    913             bcdLong |= fBCD.bcdBytes.ptr[i];
    914         }
    915         uprv_free(fBCD.bcdBytes.ptr);
    916         fBCD.bcdBytes.ptr = nullptr;
    917         fBCD.bcdLong = bcdLong;
    918         usingBytes = false;
    919     } else {
    920         // Change from long to bytes
    921         // Copy the long into a local variable since it will get munged when we allocate the bytes
    922         uint64_t bcdLong = fBCD.bcdLong;
    923         ensureCapacity();
    924         for (int i = 0; i < precision; i++) {
    925             fBCD.bcdBytes.ptr[i] = static_cast<int8_t>(bcdLong & 0xf);
    926             bcdLong >>= 4;
    927         }
    928         U_ASSERT(usingBytes);
    929     }
    930 }
    931 
    932 void DecimalQuantity::copyBcdFrom(const DecimalQuantity &other) {
    933     setBcdToZero();
    934     if (other.usingBytes) {
    935         ensureCapacity(other.precision);
    936         uprv_memcpy(fBCD.bcdBytes.ptr, other.fBCD.bcdBytes.ptr, other.precision * sizeof(int8_t));
    937     } else {
    938         fBCD.bcdLong = other.fBCD.bcdLong;
    939     }
    940 }
    941 
    942 const char16_t* DecimalQuantity::checkHealth() const {
    943     if (usingBytes) {
    944         if (precision == 0) { return u"Zero precision but we are in byte mode"; }
    945         int32_t capacity = fBCD.bcdBytes.len;
    946         if (precision > capacity) { return u"Precision exceeds length of byte array"; }
    947         if (getDigitPos(precision - 1) == 0) { return u"Most significant digit is zero in byte mode"; }
    948         if (getDigitPos(0) == 0) { return u"Least significant digit is zero in long mode"; }
    949         for (int i = 0; i < precision; i++) {
    950             if (getDigitPos(i) >= 10) { return u"Digit exceeding 10 in byte array"; }
    951             if (getDigitPos(i) < 0) { return u"Digit below 0 in byte array"; }
    952         }
    953         for (int i = precision; i < capacity; i++) {
    954             if (getDigitPos(i) != 0) { return u"Nonzero digits outside of range in byte array"; }
    955         }
    956     } else {
    957         if (precision == 0 && fBCD.bcdLong != 0) {
    958             return u"Value in bcdLong even though precision is zero";
    959         }
    960         if (precision > 16) { return u"Precision exceeds length of long"; }
    961         if (precision != 0 && getDigitPos(precision - 1) == 0) {
    962             return u"Most significant digit is zero in long mode";
    963         }
    964         if (precision != 0 && getDigitPos(0) == 0) {
    965             return u"Least significant digit is zero in long mode";
    966         }
    967         for (int i = 0; i < precision; i++) {
    968             if (getDigitPos(i) >= 10) { return u"Digit exceeding 10 in long"; }
    969             if (getDigitPos(i) < 0) { return u"Digit below 0 in long (?!)"; }
    970         }
    971         for (int i = precision; i < 16; i++) {
    972             if (getDigitPos(i) != 0) { return u"Nonzero digits outside of range in long"; }
    973         }
    974     }
    975 
    976     // No error
    977     return nullptr;
    978 }
    979 
    980 UnicodeString DecimalQuantity::toString() const {
    981     MaybeStackArray<char, 30> digits(precision + 1);
    982     for (int32_t i = 0; i < precision; i++) {
    983         digits[i] = getDigitPos(precision - i - 1) + '0';
    984     }
    985     digits[precision] = 0; // terminate buffer
    986     char buffer8[100];
    987     snprintf(
    988             buffer8,
    989             sizeof(buffer8),
    990             "<DecimalQuantity %d:%d:%d:%d %s %s%s%d>",
    991             (lOptPos > 999 ? 999 : lOptPos),
    992             lReqPos,
    993             rReqPos,
    994             (rOptPos < -999 ? -999 : rOptPos),
    995             (usingBytes ? "bytes" : "long"),
    996             (precision == 0 ? "0" : digits.getAlias()),
    997             "E",
    998             scale);
    999     return UnicodeString(buffer8, -1, US_INV);
   1000 }
   1001 
   1002 UnicodeString DecimalQuantity::toNumberString() const {
   1003     MaybeStackArray<char, 30> digits(precision + 11);
   1004     for (int32_t i = 0; i < precision; i++) {
   1005         digits[i] = getDigitPos(precision - i - 1) + '0';
   1006     }
   1007     snprintf(digits.getAlias() + precision, 11, "E%d", scale);
   1008     return UnicodeString(digits.getAlias(), -1, US_INV);
   1009 }
   1010 
   1011 #endif /* #if !UCONFIG_NO_FORMATTING */
   1012