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