Home | History | Annotate | Download | only in i18n
      1 /*
      2 **********************************************************************
      3 *   Copyright (C) 1997-2010, International Business Machines
      4 *   Corporation and others.  All Rights Reserved.
      5 **********************************************************************
      6 *
      7 * File DIGITLST.CPP
      8 *
      9 * Modification History:
     10 *
     11 *   Date        Name        Description
     12 *   03/21/97    clhuang     Converted from java.
     13 *   03/21/97    clhuang     Implemented with new APIs.
     14 *   03/27/97    helena      Updated to pass the simple test after code review.
     15 *   03/31/97    aliu        Moved isLONG_MIN to here, and fixed it.
     16 *   04/15/97    aliu        Changed MAX_COUNT to DBL_DIG.  Changed Digit to char.
     17 *                           Reworked representation by replacing fDecimalAt
     18 *                           with fExponent.
     19 *   04/16/97    aliu        Rewrote set() and getDouble() to use sprintf/atof
     20 *                           to do digit conversion.
     21 *   09/09/97    aliu        Modified for exponential notation support.
     22 *   08/02/98    stephen     Added nearest/even rounding
     23 *                            Fixed bug in fitsIntoLong
     24 ******************************************************************************
     25 */
     26 
     27 #include "digitlst.h"
     28 
     29 #if !UCONFIG_NO_FORMATTING
     30 #include "unicode/putil.h"
     31 #include "charstr.h"
     32 #include "cmemory.h"
     33 #include "cstring.h"
     34 #include "putilimp.h"
     35 #include "uassert.h"
     36 #include <stdlib.h>
     37 #include <limits.h>
     38 #include <string.h>
     39 #include <stdio.h>
     40 #ifdef ANDROID
     41 #include <math.h>
     42 #else
     43 #include <limits>
     44 #endif
     45 
     46 // ***************************************************************************
     47 // class DigitList
     48 //    A wrapper onto decNumber.
     49 //    Used to be standalone.
     50 // ***************************************************************************
     51 
     52 /**
     53  * This is the zero digit.  The base for the digits returned by getDigit()
     54  * Note that it is the platform invariant digit, and is not Unicode.
     55  */
     56 #define kZero '0'
     57 
     58 static char gDecimal = 0;
     59 
     60 /* Only for 32 bit numbers. Ignore the negative sign. */
     61 static const char LONG_MIN_REP[] = "2147483648";
     62 static const char I64_MIN_REP[] = "9223372036854775808";
     63 
     64 
     65 U_NAMESPACE_BEGIN
     66 
     67 // -------------------------------------
     68 // default constructor
     69 
     70 DigitList::DigitList()
     71 {
     72     uprv_decContextDefault(&fContext, DEC_INIT_BASE);
     73     fContext.traps  = 0;
     74     uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN);
     75     fContext.digits = fStorage.getCapacity();
     76 
     77     fDecNumber = fStorage.getAlias();
     78     uprv_decNumberZero(fDecNumber);
     79 
     80     fDouble = 0.0;
     81     fHaveDouble = TRUE;
     82 }
     83 
     84 // -------------------------------------
     85 
     86 DigitList::~DigitList()
     87 {
     88 }
     89 
     90 // -------------------------------------
     91 // copy constructor
     92 
     93 DigitList::DigitList(const DigitList &other)
     94 {
     95     fDecNumber = fStorage.getAlias();
     96     *this = other;
     97 }
     98 
     99 
    100 // -------------------------------------
    101 // assignment operator
    102 
    103 DigitList&
    104 DigitList::operator=(const DigitList& other)
    105 {
    106     if (this != &other)
    107     {
    108         uprv_memcpy(&fContext, &other.fContext, sizeof(decContext));
    109 
    110         if (other.fStorage.getCapacity() > fStorage.getCapacity()) {
    111             fDecNumber = fStorage.resize(other.fStorage.getCapacity());
    112         }
    113         // Always reset the fContext.digits, even if fDecNumber was not reallocated,
    114         // because above we copied fContext from other.fContext.
    115         fContext.digits = fStorage.getCapacity();
    116         uprv_decNumberCopy(fDecNumber, other.fDecNumber);
    117 
    118         fDouble = other.fDouble;
    119         fHaveDouble = other.fHaveDouble;
    120     }
    121     return *this;
    122 }
    123 
    124 // -------------------------------------
    125 //    operator ==  (does not exactly match the old DigitList function)
    126 
    127 UBool
    128 DigitList::operator==(const DigitList& that) const
    129 {
    130     if (this == &that) {
    131         return TRUE;
    132     }
    133     decNumber n;  // Has space for only a none digit value.
    134     decContext c;
    135     uprv_decContextDefault(&c, DEC_INIT_BASE);
    136     c.digits = 1;
    137     c.traps = 0;
    138 
    139     uprv_decNumberCompare(&n, this->fDecNumber, that.fDecNumber, &c);
    140     UBool result = decNumberIsZero(&n);
    141     return result;
    142 }
    143 
    144 // -------------------------------------
    145 //      comparison function.   Returns
    146 //         Not Comparable :  -2
    147 //                      < :  -1
    148 //                     == :   0
    149 //                      > :  +1
    150 int32_t DigitList::compare(const DigitList &other) {
    151     decNumber   result;
    152     int32_t     savedDigits = fContext.digits;
    153     fContext.digits = 1;
    154     uprv_decNumberCompare(&result, this->fDecNumber, other.fDecNumber, &fContext);
    155     fContext.digits = savedDigits;
    156     if (decNumberIsZero(&result)) {
    157         return 0;
    158     } else if (decNumberIsSpecial(&result)) {
    159         return -2;
    160     } else if (result.bits & DECNEG) {
    161         return -1;
    162     } else {
    163         return 1;
    164     }
    165 }
    166 
    167 
    168 // -------------------------------------
    169 //  Reduce - remove trailing zero digits.
    170 void
    171 DigitList::reduce() {
    172     uprv_decNumberReduce(fDecNumber, fDecNumber, &fContext);
    173 }
    174 
    175 
    176 // -------------------------------------
    177 //  trim - remove trailing fraction zero digits.
    178 void
    179 DigitList::trim() {
    180     uprv_decNumberTrim(fDecNumber);
    181 }
    182 
    183 // -------------------------------------
    184 // Resets the digit list; sets all the digits to zero.
    185 
    186 void
    187 DigitList::clear()
    188 {
    189     uprv_decNumberZero(fDecNumber);
    190     uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN);
    191     fDouble = 0.0;
    192     fHaveDouble = TRUE;
    193 }
    194 
    195 
    196 /**
    197  * Formats a int64_t number into a base 10 string representation, and NULL terminates it.
    198  * @param number The number to format
    199  * @param outputStr The string to output to.  Must be at least MAX_DIGITS+2 in length (21),
    200  *                  to hold the longest int64_t value.
    201  * @return the number of digits written, not including the sign.
    202  */
    203 static int32_t
    204 formatBase10(int64_t number, char *outputStr) {
    205     // The number is output backwards, starting with the LSD.
    206     // Fill the buffer from the far end.  After the number is complete,
    207     // slide the string contents to the front.
    208 
    209     const int32_t MAX_IDX = MAX_DIGITS+2;
    210     int32_t destIdx = MAX_IDX;
    211     outputStr[--destIdx] = 0;
    212 
    213     int64_t  n = number;
    214     if (number < 0) {   // Negative numbers are slightly larger than a postive
    215         outputStr[--destIdx] = (char)(-(n % 10) + kZero);
    216         n /= -10;
    217     }
    218     do {
    219         outputStr[--destIdx] = (char)(n % 10 + kZero);
    220         n /= 10;
    221     } while (n > 0);
    222 
    223     if (number < 0) {
    224         outputStr[--destIdx] = '-';
    225     }
    226 
    227     // Slide the number to the start of the output str
    228     U_ASSERT(destIdx >= 0);
    229     int32_t length = MAX_IDX - destIdx;
    230     uprv_memmove(outputStr, outputStr+MAX_IDX-length, length);
    231 
    232     return length;
    233 }
    234 
    235 
    236 // -------------------------------------
    237 
    238 void
    239 DigitList::setRoundingMode(DecimalFormat::ERoundingMode m) {
    240     enum rounding r;
    241 
    242     switch (m) {
    243       case  DecimalFormat::kRoundCeiling:  r = DEC_ROUND_CEILING;   break;
    244       case  DecimalFormat::kRoundFloor:    r = DEC_ROUND_FLOOR;     break;
    245       case  DecimalFormat::kRoundDown:     r = DEC_ROUND_DOWN;      break;
    246       case  DecimalFormat::kRoundUp:       r = DEC_ROUND_UP;        break;
    247       case  DecimalFormat::kRoundHalfEven: r = DEC_ROUND_HALF_EVEN; break;
    248       case  DecimalFormat::kRoundHalfDown: r = DEC_ROUND_HALF_DOWN; break;
    249       case  DecimalFormat::kRoundHalfUp:   r = DEC_ROUND_HALF_UP;   break;
    250       default:
    251          // TODO: how to report the problem?
    252          // Leave existing mode unchanged.
    253          r = uprv_decContextGetRounding(&fContext);
    254     }
    255     uprv_decContextSetRounding(&fContext, r);
    256 
    257 }
    258 
    259 
    260 // -------------------------------------
    261 
    262 void
    263 DigitList::setPositive(UBool s) {
    264     if (s) {
    265         fDecNumber->bits &= ~DECNEG;
    266     } else {
    267         fDecNumber->bits |= DECNEG;
    268     }
    269     fHaveDouble = FALSE;
    270 }
    271 // -------------------------------------
    272 
    273 void
    274 DigitList::setDecimalAt(int32_t d) {
    275     U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0);  // Not Infinity or NaN
    276     U_ASSERT(d-1>-999999999);
    277     U_ASSERT(d-1< 999999999);
    278     int32_t adjustedDigits = fDecNumber->digits;
    279     if (decNumberIsZero(fDecNumber)) {
    280         // Account for difference in how zero is represented between DigitList & decNumber.
    281         adjustedDigits = 0;
    282     }
    283     fDecNumber->exponent = d - adjustedDigits;
    284     fHaveDouble = FALSE;
    285 }
    286 
    287 int32_t
    288 DigitList::getDecimalAt() {
    289     U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0);  // Not Infinity or NaN
    290     if (decNumberIsZero(fDecNumber) || ((fDecNumber->bits & DECSPECIAL) != 0)) {
    291         return fDecNumber->exponent;  // Exponent should be zero for these cases.
    292     }
    293     return fDecNumber->exponent + fDecNumber->digits;
    294 }
    295 
    296 void
    297 DigitList::setCount(int32_t c)  {
    298     U_ASSERT(c <= fContext.digits);
    299     if (c == 0) {
    300         // For a value of zero, DigitList sets all fields to zero, while
    301         // decNumber keeps one digit (with that digit being a zero)
    302         c = 1;
    303         fDecNumber->lsu[0] = 0;
    304     }
    305     fDecNumber->digits = c;
    306     fHaveDouble = FALSE;
    307 }
    308 
    309 int32_t
    310 DigitList::getCount() const {
    311     if (decNumberIsZero(fDecNumber) && fDecNumber->exponent==0) {
    312        // The extra test for exponent==0 is needed because parsing sometimes appends
    313        // zero digits.  It's bogus, decimalFormatter parsing needs to be cleaned up.
    314        return 0;
    315     } else {
    316        return fDecNumber->digits;
    317     }
    318 }
    319 
    320 void
    321 DigitList::setDigit(int32_t i, char v) {
    322     int32_t count = fDecNumber->digits;
    323     U_ASSERT(i<count);
    324     U_ASSERT(v>='0' && v<='9');
    325     v &= 0x0f;
    326     fDecNumber->lsu[count-i-1] = v;
    327     fHaveDouble = FALSE;
    328 }
    329 
    330 char
    331 DigitList::getDigit(int32_t i) {
    332     int32_t count = fDecNumber->digits;
    333     U_ASSERT(i<count);
    334     return fDecNumber->lsu[count-i-1] + '0';
    335 }
    336 
    337 // copied from DigitList::getDigit()
    338 uint8_t
    339 DigitList::getDigitValue(int32_t i) {
    340     int32_t count = fDecNumber->digits;
    341     U_ASSERT(i<count);
    342     return fDecNumber->lsu[count-i-1];
    343 }
    344 
    345 // -------------------------------------
    346 // Appends the digit to the digit list if it's not out of scope.
    347 // Ignores the digit, otherwise.
    348 //
    349 // This function is horribly inefficient to implement with decNumber because
    350 // the digits are stored least significant first, which requires moving all
    351 // existing digits down one to make space for the new one to be appended.
    352 //
    353 void
    354 DigitList::append(char digit)
    355 {
    356     U_ASSERT(digit>='0' && digit<='9');
    357     // Ignore digits which exceed the precision we can represent
    358     //    And don't fix for larger precision.  Fix callers instead.
    359     if (decNumberIsZero(fDecNumber)) {
    360         // Zero needs to be special cased because of the difference in the way
    361         // that the old DigitList and decNumber represent it.
    362         // digit cout was zero for digitList, is one for decNumber
    363         fDecNumber->lsu[0] = digit & 0x0f;
    364         fDecNumber->digits = 1;
    365         fDecNumber->exponent--;     // To match the old digit list implementation.
    366     } else {
    367         int32_t nDigits = fDecNumber->digits;
    368         if (nDigits < fContext.digits) {
    369             int i;
    370             for (i=nDigits; i>0; i--) {
    371                 fDecNumber->lsu[i] = fDecNumber->lsu[i-1];
    372             }
    373             fDecNumber->lsu[0] = digit & 0x0f;
    374             fDecNumber->digits++;
    375             // DigitList emulation - appending doesn't change the magnitude of existing
    376             //                       digits.  With decNumber's decimal being after the
    377             //                       least signficant digit, we need to adjust the exponent.
    378             fDecNumber->exponent--;
    379         }
    380     }
    381     fHaveDouble = FALSE;
    382 }
    383 
    384 // -------------------------------------
    385 
    386 /**
    387  * Currently, getDouble() depends on atof() to do its conversion.
    388  *
    389  * WARNING!!
    390  * This is an extremely costly function. ~1/2 of the conversion time
    391  * can be linked to this function.
    392  */
    393 double
    394 DigitList::getDouble() const
    395 {
    396     // TODO:  fix thread safety.  Can probably be finessed some by analyzing
    397     //        what public const functions can see which DigitLists.
    398     //        Like precompute fDouble for DigitLists coming in from a parse
    399     //        or from a Formattable::set(), but not for any others.
    400     if (fHaveDouble) {
    401         return fDouble;
    402     }
    403     DigitList *nonConstThis = const_cast<DigitList *>(this);
    404 
    405     if (gDecimal == 0) {
    406         char rep[MAX_DIGITS];
    407         // For machines that decide to change the decimal on you,
    408         // and try to be too smart with localization.
    409         // This normally should be just a '.'.
    410         sprintf(rep, "%+1.1f", 1.0);
    411         gDecimal = rep[2];
    412     }
    413 
    414     if (isZero()) {
    415         nonConstThis->fDouble = 0.0;
    416         if (decNumberIsNegative(fDecNumber)) {
    417             nonConstThis->fDouble /= -1;
    418         }
    419     } else if (isInfinite()) {
    420         // BEGIN android-changed
    421         // There is no numeric_limits template member in Android std nor
    422         // INFINITY defined in math.h of ICU Linux build.
    423 #ifdef INFINITY
    424         nonConstThis->fDouble = INFINITY;
    425 #else
    426         if (std::numeric_limits<double>::has_infinity) {
    427             nonConstThis->fDouble = std::numeric_limits<double>::infinity();
    428         } else {
    429             nonConstThis->fDouble = std::numeric_limits<double>::max();
    430         }
    431 #endif
    432         // END android-changed
    433 
    434         if (!isPositive()) {
    435             nonConstThis->fDouble = -fDouble;
    436         }
    437     } else {
    438         MaybeStackArray<char, MAX_DBL_DIGITS+18> s;
    439            // Note:  14 is a  magic constant from the decNumber library documentation,
    440            //        the max number of extra characters beyond the number of digits
    441            //        needed to represent the number in string form.  Add a few more
    442            //        for the additional digits we retain.
    443 
    444         // Round down to appx. double precision, if the number is longer than that.
    445         // Copy the number first, so that we don't modify the original.
    446         if (getCount() > MAX_DBL_DIGITS + 3) {
    447             DigitList numToConvert(*this);
    448             numToConvert.reduce();    // Removes any trailing zeros, so that digit count is good.
    449             numToConvert.round(MAX_DBL_DIGITS+3);
    450             uprv_decNumberToString(numToConvert.fDecNumber, s);
    451             // TODO:  how many extra digits should be included for an accurate conversion?
    452         } else {
    453             uprv_decNumberToString(this->fDecNumber, s);
    454         }
    455         U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18);
    456 
    457         if (gDecimal != '.') {
    458             char *decimalPt = strchr(s, '.');
    459             if (decimalPt != NULL) {
    460                 *decimalPt = gDecimal;
    461             }
    462         }
    463         char *end = NULL;
    464         nonConstThis->fDouble = uprv_strtod(s, &end);
    465     }
    466     nonConstThis->fHaveDouble = TRUE;
    467     return fDouble;
    468 }
    469 
    470 // -------------------------------------
    471 
    472 /**
    473  *  convert this number to an int32_t.   Round if there is a fractional part.
    474  *  Return zero if the number cannot be represented.
    475  */
    476 int32_t DigitList::getLong() /*const*/
    477 {
    478     int32_t result = 0;
    479     if (fDecNumber->digits + fDecNumber->exponent > 10) {
    480         // Overflow, absolute value too big.
    481         return result;
    482     }
    483     if (fDecNumber->exponent != 0) {
    484         // Force to an integer, with zero exponent, rounding if necessary.
    485         //   (decNumberToInt32 will only work if the exponent is exactly zero.)
    486         DigitList copy(*this);
    487         DigitList zero;
    488         uprv_decNumberQuantize(copy.fDecNumber, copy.fDecNumber, zero.fDecNumber, &fContext);
    489         result = uprv_decNumberToInt32(copy.fDecNumber, &fContext);
    490     } else {
    491         result = uprv_decNumberToInt32(fDecNumber, &fContext);
    492     }
    493     return result;
    494 }
    495 
    496 /**
    497  *  convert this number to an int64_t.   Truncate if there is a fractional part.
    498  *  Return zero if the number cannot be represented.
    499  */
    500 int64_t DigitList::getInt64() /*const*/ {
    501     // BEGIN android-change
    502     // Apply the changes for ICU ticket#8199 to avoid the crash in DigitList::getInt64().
    503     // The fixes are in ICU4.8.
    504     // See http://bugs.icu-project.org/trac/ticket/8199 for details.
    505 
    506     // Truncate if non-integer.
    507     // Return 0 if out of range.
    508     // Range of in64_t is -9223372036854775808 to 9223372036854775807  (19 digits)
    509     //
    510     if (fDecNumber->digits + fDecNumber->exponent > 19) {
    511         // Overflow, absolute value too big.
    512         return 0;
    513     }
    514 
    515     // The number of integer digits may differ from the number of digits stored
    516     //   in the decimal number.
    517     //     for 12.345  numIntDigits = 2, number->digits = 5
    518     //     for 12E4    numIntDigits = 6, number->digits = 2
    519     // The conversion ignores the fraction digits in the first case,
    520     // and fakes up extra zero digits in the second.
    521     // TODO:  It would be faster to store a table of powers of ten to multiply by
    522     //        instead of looping over zero digits, multiplying each time.
    523 
    524     int32_t numIntDigits = fDecNumber->digits + fDecNumber->exponent;
    525     uint64_t value = 0;
    526     for (int32_t i = 0; i < numIntDigits; i++) {
    527         // Loop is iterating over digits starting with the most significant.
    528         // Numbers are stored with the least significant digit at index zero.
    529         int32_t digitIndex = fDecNumber->digits - i - 1;
    530         int32_t v = (digitIndex >= 0) ? fDecNumber->lsu[digitIndex] : 0;
    531         value = value * (uint64_t)10 + (uint64_t)v;
    532     }
    533 
    534     if (decNumberIsNegative(fDecNumber)) {
    535         value = ~value;
    536         value += 1;
    537     }
    538     int64_t svalue = (int64_t)value;
    539 
    540     // Check overflow.  It's convenient that the MSD is 9 only on overflow, the amount of
    541     //                  overflow can't wrap too far.  The test will also fail -0, but
    542     //                  that does no harm; the right answer is 0.
    543     if (numIntDigits == 19) {
    544         if (( decNumberIsNegative(fDecNumber) && svalue>0) ||
    545             (!decNumberIsNegative(fDecNumber) && svalue<0)) {
    546             svalue = 0;
    547         }
    548     }
    549     // END android-change
    550 
    551     return svalue;
    552 }
    553 
    554 /**
    555  *  Return a string form of this number.
    556  *     Format is as defined by the decNumber library, for interchange of
    557  *     decimal numbers.
    558  */
    559 void DigitList::getDecimal(CharString &str, UErrorCode &status) {
    560     if (U_FAILURE(status)) {
    561         return;
    562     }
    563 
    564     // A decimal number in string form can, worst case, be 14 characters longer
    565     //  than the number of digits.  So says the decNumber library doc.
    566     int32_t maxLength = fDecNumber->digits + 14;
    567     int32_t capacity = 0;
    568     char *buffer = str.clear().getAppendBuffer(maxLength, 0, capacity, status);
    569     if (U_FAILURE(status)) {
    570         return;    // Memory allocation error on growing the string.
    571     }
    572     U_ASSERT(capacity >= maxLength);
    573     uprv_decNumberToString(this->fDecNumber, buffer);
    574     U_ASSERT((int32_t)uprv_strlen(buffer) <= maxLength);
    575     str.append(buffer, -1, status);
    576 }
    577 
    578 /**
    579  * Return true if this is an integer value that can be held
    580  * by an int32_t type.
    581  */
    582 UBool
    583 DigitList::fitsIntoLong(UBool ignoreNegativeZero) /*const*/
    584 {
    585     if (decNumberIsSpecial(this->fDecNumber)) {
    586         // NaN or Infinity.  Does not fit in int32.
    587         return FALSE;
    588     }
    589     uprv_decNumberTrim(this->fDecNumber);
    590     if (fDecNumber->exponent < 0) {
    591         // Number contains fraction digits.
    592         return FALSE;
    593     }
    594     if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero &&
    595         (fDecNumber->bits & DECNEG) != 0) {
    596         // Negative Zero, not ingored.  Cannot represent as a long.
    597         return FALSE;
    598     }
    599     if (fDecNumber->digits + fDecNumber->exponent < 10) {
    600         // The number is 9 or fewer digits.
    601         // The max and min int32 are 10 digts, so this number fits.
    602         // This is the common case.
    603         return TRUE;
    604     }
    605 
    606     // TODO:  Should cache these constants; construction is relatively costly.
    607     //        But not of huge consequence; they're only needed for 10 digit ints.
    608     UErrorCode status = U_ZERO_ERROR;
    609     DigitList min32; min32.set("-2147483648", status);
    610     if (this->compare(min32) < 0) {
    611         return FALSE;
    612     }
    613     DigitList max32; max32.set("2147483647", status);
    614     if (this->compare(max32) > 0) {
    615         return FALSE;
    616     }
    617     if (U_FAILURE(status)) {
    618         return FALSE;
    619     }
    620     return true;
    621 }
    622 
    623 
    624 
    625 /**
    626  * Return true if the number represented by this object can fit into
    627  * a long.
    628  */
    629 UBool
    630 DigitList::fitsIntoInt64(UBool ignoreNegativeZero) /*const*/
    631 {
    632     if (decNumberIsSpecial(this->fDecNumber)) {
    633         // NaN or Infinity.  Does not fit in int32.
    634         return FALSE;
    635     }
    636     uprv_decNumberTrim(this->fDecNumber);
    637     if (fDecNumber->exponent < 0) {
    638         // Number contains fraction digits.
    639         return FALSE;
    640     }
    641     if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero &&
    642         (fDecNumber->bits & DECNEG) != 0) {
    643         // Negative Zero, not ingored.  Cannot represent as a long.
    644         return FALSE;
    645     }
    646     if (fDecNumber->digits + fDecNumber->exponent < 19) {
    647         // The number is 18 or fewer digits.
    648         // The max and min int64 are 19 digts, so this number fits.
    649         // This is the common case.
    650         return TRUE;
    651     }
    652 
    653     // TODO:  Should cache these constants; construction is relatively costly.
    654     //        But not of huge consequence; they're only needed for 19 digit ints.
    655     UErrorCode status = U_ZERO_ERROR;
    656     DigitList min64; min64.set("-9223372036854775808", status);
    657     if (this->compare(min64) < 0) {
    658         return FALSE;
    659     }
    660     DigitList max64; max64.set("9223372036854775807", status);
    661     if (this->compare(max64) > 0) {
    662         return FALSE;
    663     }
    664     if (U_FAILURE(status)) {
    665         return FALSE;
    666     }
    667     return true;
    668 }
    669 
    670 
    671 // -------------------------------------
    672 
    673 void
    674 DigitList::set(int32_t source)
    675 {
    676     set((int64_t)source);
    677     fDouble = source;
    678     fHaveDouble = TRUE;
    679 }
    680 
    681 // -------------------------------------
    682 /**
    683  * @param maximumDigits The maximum digits to be generated.  If zero,
    684  * there is no maximum -- generate all digits.
    685  */
    686 void
    687 DigitList::set(int64_t source)
    688 {
    689     char str[MAX_DIGITS+2];   // Leave room for sign and trailing nul.
    690     formatBase10(source, str);
    691     U_ASSERT(uprv_strlen(str) < sizeof(str));
    692 
    693     uprv_decNumberFromString(fDecNumber, str, &fContext);
    694     fDouble = (double)source;
    695     fHaveDouble = TRUE;
    696 }
    697 
    698 
    699 // -------------------------------------
    700 /**
    701  * Set the DigitList from a decimal number string.
    702  *
    703  * The incoming string _must_ be nul terminated, even though it is arriving
    704  * as a StringPiece because that is what the decNumber library wants.
    705  * We can get away with this for an internal function; it would not
    706  * be acceptable for a public API.
    707  */
    708 void
    709 DigitList::set(const StringPiece &source, UErrorCode &status) {
    710     if (U_FAILURE(status)) {
    711         return;
    712     }
    713 
    714     // Figure out a max number of digits to use during the conversion, and
    715     // resize the number up if necessary.
    716     int32_t numDigits = source.length();
    717     if (numDigits > fContext.digits) {
    718         // fContext.digits == fStorage.getCapacity()
    719         decNumber *t = fStorage.resize(numDigits, fStorage.getCapacity());
    720         if (t == NULL) {
    721             status = U_MEMORY_ALLOCATION_ERROR;
    722             return;
    723         }
    724         fDecNumber = t;
    725         fContext.digits = numDigits;
    726     }
    727 
    728     fContext.status = 0;
    729     uprv_decNumberFromString(fDecNumber, source.data(), &fContext);
    730     if ((fContext.status & DEC_Conversion_syntax) != 0) {
    731         status = U_DECIMAL_NUMBER_SYNTAX_ERROR;
    732     }
    733     fHaveDouble = FALSE;
    734 }
    735 
    736 /**
    737  * Set the digit list to a representation of the given double value.
    738  * This method supports both fixed-point and exponential notation.
    739  * @param source Value to be converted.
    740  */
    741 void
    742 DigitList::set(double source)
    743 {
    744     // for now, simple implementation; later, do proper IEEE stuff
    745     char rep[MAX_DIGITS + 8]; // Extra space for '+', '.', e+NNN, and '\0' (actually +8 is enough)
    746 
    747     // Generate a representation of the form /[+-][0-9]+e[+-][0-9]+/
    748     sprintf(rep, "%+1.*e", MAX_DBL_DIGITS - 1, source);
    749     U_ASSERT(uprv_strlen(rep) < sizeof(rep));
    750 
    751     // Create a decNumber from the string.
    752     uprv_decNumberFromString(fDecNumber, rep, &fContext);
    753     uprv_decNumberTrim(fDecNumber);
    754     fDouble = source;
    755     fHaveDouble = TRUE;
    756 }
    757 
    758 // -------------------------------------
    759 
    760 /*
    761  * Multiply
    762  *      The number will be expanded if need be to retain full precision.
    763  *      In practice, for formatting, multiply is by 10, 100 or 1000, so more digits
    764  *      will not be required for this use.
    765  */
    766 void
    767 DigitList::mult(const DigitList &other, UErrorCode &status) {
    768     fContext.status = 0;
    769     int32_t requiredDigits = this->digits() + other.digits();
    770     if (requiredDigits > fContext.digits) {
    771         reduce();    // Remove any trailing zeros
    772         int32_t requiredDigits = this->digits() + other.digits();
    773         ensureCapacity(requiredDigits, status);
    774     }
    775     uprv_decNumberMultiply(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
    776     fHaveDouble = FALSE;
    777 }
    778 
    779 // -------------------------------------
    780 
    781 /*
    782  * Divide
    783  *      The number will _not_ be expanded for inexact results.
    784  *      TODO:  probably should expand some, for rounding increments that
    785  *             could add a few digits, e.g. .25, but not expand arbitrarily.
    786  */
    787 void
    788 DigitList::div(const DigitList &other, UErrorCode &status) {
    789     if (U_FAILURE(status)) {
    790         return;
    791     }
    792     uprv_decNumberDivide(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
    793     fHaveDouble = FALSE;
    794 }
    795 
    796 // -------------------------------------
    797 
    798 /*
    799  * ensureCapacity.   Grow the digit storage for the number if it's less than the requested
    800  *         amount.  Never reduce it.  Available size is kept in fContext.digits.
    801  */
    802 void
    803 DigitList::ensureCapacity(int32_t requestedCapacity, UErrorCode &status) {
    804     if (U_FAILURE(status)) {
    805         return;
    806     }
    807     if (requestedCapacity <= 0) {
    808         status = U_ILLEGAL_ARGUMENT_ERROR;
    809         return;
    810     }
    811     if (requestedCapacity > DEC_MAX_DIGITS) {
    812         // Don't report an error for requesting too much.
    813         // Arithemetic Results will be rounded to what can be supported.
    814         //   At 999,999,999 max digits, exceeding the limit is not too likely!
    815         requestedCapacity = DEC_MAX_DIGITS;
    816     }
    817     if (requestedCapacity > fContext.digits) {
    818         decNumber *newBuffer = fStorage.resize(requestedCapacity, fStorage.getCapacity());
    819         if (newBuffer == NULL) {
    820             status = U_MEMORY_ALLOCATION_ERROR;
    821             return;
    822         }
    823         fContext.digits = requestedCapacity;
    824         fDecNumber = newBuffer;
    825     }
    826 }
    827 
    828 // -------------------------------------
    829 
    830 /**
    831  * Round the representation to the given number of digits.
    832  * @param maximumDigits The maximum number of digits to be shown.
    833  * Upon return, count will be less than or equal to maximumDigits.
    834  */
    835 void
    836 DigitList::round(int32_t maximumDigits)
    837 {
    838     int32_t savedDigits  = fContext.digits;
    839     fContext.digits = maximumDigits;
    840     uprv_decNumberPlus(fDecNumber, fDecNumber, &fContext);
    841     fContext.digits = savedDigits;
    842     uprv_decNumberTrim(fDecNumber);
    843     fHaveDouble = FALSE;
    844 }
    845 
    846 
    847 void
    848 DigitList::roundFixedPoint(int32_t maximumFractionDigits) {
    849     trim();        // Remove trailing zeros.
    850     if (fDecNumber->exponent >= -maximumFractionDigits) {
    851         return;
    852     }
    853     decNumber scale;   // Dummy decimal number, but with the desired number of
    854     uprv_decNumberZero(&scale);    //    fraction digits.
    855     scale.exponent = -maximumFractionDigits;
    856     scale.lsu[0] = 1;
    857 
    858     uprv_decNumberQuantize(fDecNumber, fDecNumber, &scale, &fContext);
    859     trim();
    860     fHaveDouble = FALSE;
    861 }
    862 
    863 // -------------------------------------
    864 
    865 void
    866 DigitList::toIntegralValue() {
    867     uprv_decNumberToIntegralValue(fDecNumber, fDecNumber, &fContext);
    868 }
    869 
    870 
    871 // -------------------------------------
    872 UBool
    873 DigitList::isZero() const
    874 {
    875     return decNumberIsZero(fDecNumber);
    876 }
    877 
    878 
    879 U_NAMESPACE_END
    880 #endif // #if !UCONFIG_NO_FORMATTING
    881 
    882 //eof
    883