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