Home | History | Annotate | Download | only in i18n
      1 /*
      2 **********************************************************************
      3 *   Copyright (C) 1997-2015, 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 "mutex.h"
     35 #include "putilimp.h"
     36 #include "uassert.h"
     37 #include "digitinterval.h"
     38 #include <stdlib.h>
     39 #include <limits.h>
     40 #include <string.h>
     41 #include <stdio.h>
     42 #include <limits>
     43 
     44 // ***************************************************************************
     45 // class DigitList
     46 //    A wrapper onto decNumber.
     47 //    Used to be standalone.
     48 // ***************************************************************************
     49 
     50 /**
     51  * This is the zero digit.  The base for the digits returned by getDigit()
     52  * Note that it is the platform invariant digit, and is not Unicode.
     53  */
     54 #define kZero '0'
     55 
     56 
     57 /* Only for 32 bit numbers. Ignore the negative sign. */
     58 //static const char LONG_MIN_REP[] = "2147483648";
     59 //static const char I64_MIN_REP[] = "9223372036854775808";
     60 
     61 
     62 U_NAMESPACE_BEGIN
     63 
     64 // -------------------------------------
     65 // default constructor
     66 
     67 DigitList::DigitList()
     68 {
     69     uprv_decContextDefault(&fContext, DEC_INIT_BASE);
     70     fContext.traps  = 0;
     71     uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN);
     72     fContext.digits = fStorage.getCapacity();
     73 
     74     fDecNumber = fStorage.getAlias();
     75     uprv_decNumberZero(fDecNumber);
     76 
     77     internalSetDouble(0.0);
     78 }
     79 
     80 // -------------------------------------
     81 
     82 DigitList::~DigitList()
     83 {
     84 }
     85 
     86 // -------------------------------------
     87 // copy constructor
     88 
     89 DigitList::DigitList(const DigitList &other)
     90 {
     91     fDecNumber = fStorage.getAlias();
     92     *this = other;
     93 }
     94 
     95 
     96 // -------------------------------------
     97 // assignment operator
     98 
     99 DigitList&
    100 DigitList::operator=(const DigitList& other)
    101 {
    102     if (this != &other)
    103     {
    104         uprv_memcpy(&fContext, &other.fContext, sizeof(decContext));
    105 
    106         if (other.fStorage.getCapacity() > fStorage.getCapacity()) {
    107             fDecNumber = fStorage.resize(other.fStorage.getCapacity());
    108         }
    109         // Always reset the fContext.digits, even if fDecNumber was not reallocated,
    110         // because above we copied fContext from other.fContext.
    111         fContext.digits = fStorage.getCapacity();
    112         uprv_decNumberCopy(fDecNumber, other.fDecNumber);
    113 
    114         {
    115             // fDouble is lazily created and cached.
    116             // Avoid potential races with that happening with other.fDouble
    117             // while we are doing the assignment.
    118             Mutex mutex;
    119 
    120             if(other.fHave==kDouble) {
    121               fUnion.fDouble = other.fUnion.fDouble;
    122             } else if(other.fHave==kInt64) {
    123               fUnion.fInt64 = other.fUnion.fInt64;
    124             }
    125             fHave = other.fHave;
    126         }
    127     }
    128     return *this;
    129 }
    130 
    131 // -------------------------------------
    132 //    operator ==  (does not exactly match the old DigitList function)
    133 
    134 UBool
    135 DigitList::operator==(const DigitList& that) const
    136 {
    137     if (this == &that) {
    138         return TRUE;
    139     }
    140     decNumber n;  // Has space for only a none digit value.
    141     decContext c;
    142     uprv_decContextDefault(&c, DEC_INIT_BASE);
    143     c.digits = 1;
    144     c.traps = 0;
    145 
    146     uprv_decNumberCompare(&n, this->fDecNumber, that.fDecNumber, &c);
    147     UBool result = decNumberIsZero(&n);
    148     return result;
    149 }
    150 
    151 // -------------------------------------
    152 //      comparison function.   Returns
    153 //         Not Comparable :  -2
    154 //                      < :  -1
    155 //                     == :   0
    156 //                      > :  +1
    157 int32_t DigitList::compare(const DigitList &other) {
    158     decNumber   result;
    159     int32_t     savedDigits = fContext.digits;
    160     fContext.digits = 1;
    161     uprv_decNumberCompare(&result, this->fDecNumber, other.fDecNumber, &fContext);
    162     fContext.digits = savedDigits;
    163     if (decNumberIsZero(&result)) {
    164         return 0;
    165     } else if (decNumberIsSpecial(&result)) {
    166         return -2;
    167     } else if (result.bits & DECNEG) {
    168         return -1;
    169     } else {
    170         return 1;
    171     }
    172 }
    173 
    174 
    175 // -------------------------------------
    176 //  Reduce - remove trailing zero digits.
    177 void
    178 DigitList::reduce() {
    179     uprv_decNumberReduce(fDecNumber, fDecNumber, &fContext);
    180 }
    181 
    182 
    183 // -------------------------------------
    184 //  trim - remove trailing fraction zero digits.
    185 void
    186 DigitList::trim() {
    187     uprv_decNumberTrim(fDecNumber);
    188 }
    189 
    190 // -------------------------------------
    191 // Resets the digit list; sets all the digits to zero.
    192 
    193 void
    194 DigitList::clear()
    195 {
    196     uprv_decNumberZero(fDecNumber);
    197     uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN);
    198     internalSetDouble(0.0);
    199 }
    200 
    201 
    202 /**
    203  * Formats a int64_t number into a base 10 string representation, and NULL terminates it.
    204  * @param number The number to format
    205  * @param outputStr The string to output to.  Must be at least MAX_DIGITS+2 in length (21),
    206  *                  to hold the longest int64_t value.
    207  * @return the number of digits written, not including the sign.
    208  */
    209 static int32_t
    210 formatBase10(int64_t number, char *outputStr) {
    211     // The number is output backwards, starting with the LSD.
    212     // Fill the buffer from the far end.  After the number is complete,
    213     // slide the string contents to the front.
    214 
    215     const int32_t MAX_IDX = MAX_DIGITS+2;
    216     int32_t destIdx = MAX_IDX;
    217     outputStr[--destIdx] = 0;
    218 
    219     int64_t  n = number;
    220     if (number < 0) {   // Negative numbers are slightly larger than a postive
    221         outputStr[--destIdx] = (char)(-(n % 10) + kZero);
    222         n /= -10;
    223     }
    224     do {
    225         outputStr[--destIdx] = (char)(n % 10 + kZero);
    226         n /= 10;
    227     } while (n > 0);
    228 
    229     if (number < 0) {
    230         outputStr[--destIdx] = '-';
    231     }
    232 
    233     // Slide the number to the start of the output str
    234     U_ASSERT(destIdx >= 0);
    235     int32_t length = MAX_IDX - destIdx;
    236     uprv_memmove(outputStr, outputStr+MAX_IDX-length, length);
    237 
    238     return length;
    239 }
    240 
    241 
    242 // -------------------------------------
    243 //
    244 //  setRoundingMode()
    245 //    For most modes, the meaning and names are the same between the decNumber library
    246 //      (which DigitList follows) and the ICU Formatting Rounding Mode values.
    247 //      The flag constants are different, however.
    248 //
    249 //     Note that ICU's kRoundingUnnecessary is not implemented directly by DigitList.
    250 //     This mode, inherited from Java, means that numbers that would not format exactly
    251 //     will return an error when formatting is attempted.
    252 
    253 void
    254 DigitList::setRoundingMode(DecimalFormat::ERoundingMode m) {
    255     enum rounding r;
    256 
    257     switch (m) {
    258       case  DecimalFormat::kRoundCeiling:  r = DEC_ROUND_CEILING;   break;
    259       case  DecimalFormat::kRoundFloor:    r = DEC_ROUND_FLOOR;     break;
    260       case  DecimalFormat::kRoundDown:     r = DEC_ROUND_DOWN;      break;
    261       case  DecimalFormat::kRoundUp:       r = DEC_ROUND_UP;        break;
    262       case  DecimalFormat::kRoundHalfEven: r = DEC_ROUND_HALF_EVEN; break;
    263       case  DecimalFormat::kRoundHalfDown: r = DEC_ROUND_HALF_DOWN; break;
    264       case  DecimalFormat::kRoundHalfUp:   r = DEC_ROUND_HALF_UP;   break;
    265       case  DecimalFormat::kRoundUnnecessary: r = DEC_ROUND_HALF_EVEN; break;
    266       default:
    267          // TODO: how to report the problem?
    268          // Leave existing mode unchanged.
    269          r = uprv_decContextGetRounding(&fContext);
    270     }
    271     uprv_decContextSetRounding(&fContext, r);
    272 
    273 }
    274 
    275 
    276 // -------------------------------------
    277 
    278 void
    279 DigitList::setPositive(UBool s) {
    280     if (s) {
    281         fDecNumber->bits &= ~DECNEG;
    282     } else {
    283         fDecNumber->bits |= DECNEG;
    284     }
    285     internalClear();
    286 }
    287 // -------------------------------------
    288 
    289 void
    290 DigitList::setDecimalAt(int32_t d) {
    291     U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0);  // Not Infinity or NaN
    292     U_ASSERT(d-1>-999999999);
    293     U_ASSERT(d-1< 999999999);
    294     int32_t adjustedDigits = fDecNumber->digits;
    295     if (decNumberIsZero(fDecNumber)) {
    296         // Account for difference in how zero is represented between DigitList & decNumber.
    297         adjustedDigits = 0;
    298     }
    299     fDecNumber->exponent = d - adjustedDigits;
    300     internalClear();
    301 }
    302 
    303 int32_t
    304 DigitList::getDecimalAt() {
    305     U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0);  // Not Infinity or NaN
    306     if (decNumberIsZero(fDecNumber) || ((fDecNumber->bits & DECSPECIAL) != 0)) {
    307         return fDecNumber->exponent;  // Exponent should be zero for these cases.
    308     }
    309     return fDecNumber->exponent + fDecNumber->digits;
    310 }
    311 
    312 void
    313 DigitList::setCount(int32_t c)  {
    314     U_ASSERT(c <= fContext.digits);
    315     if (c == 0) {
    316         // For a value of zero, DigitList sets all fields to zero, while
    317         // decNumber keeps one digit (with that digit being a zero)
    318         c = 1;
    319         fDecNumber->lsu[0] = 0;
    320     }
    321     fDecNumber->digits = c;
    322     internalClear();
    323 }
    324 
    325 int32_t
    326 DigitList::getCount() const {
    327     if (decNumberIsZero(fDecNumber) && fDecNumber->exponent==0) {
    328        // The extra test for exponent==0 is needed because parsing sometimes appends
    329        // zero digits.  It's bogus, decimalFormatter parsing needs to be cleaned up.
    330        return 0;
    331     } else {
    332        return fDecNumber->digits;
    333     }
    334 }
    335 
    336 void
    337 DigitList::setDigit(int32_t i, char v) {
    338     int32_t count = fDecNumber->digits;
    339     U_ASSERT(i<count);
    340     U_ASSERT(v>='0' && v<='9');
    341     v &= 0x0f;
    342     fDecNumber->lsu[count-i-1] = v;
    343     internalClear();
    344 }
    345 
    346 char
    347 DigitList::getDigit(int32_t i) {
    348     int32_t count = fDecNumber->digits;
    349     U_ASSERT(i<count);
    350     return fDecNumber->lsu[count-i-1] + '0';
    351 }
    352 
    353 // copied from DigitList::getDigit()
    354 uint8_t
    355 DigitList::getDigitValue(int32_t i) {
    356     int32_t count = fDecNumber->digits;
    357     U_ASSERT(i<count);
    358     return fDecNumber->lsu[count-i-1];
    359 }
    360 
    361 // -------------------------------------
    362 // Appends the digit to the digit list if it's not out of scope.
    363 // Ignores the digit, otherwise.
    364 //
    365 // This function is horribly inefficient to implement with decNumber because
    366 // the digits are stored least significant first, which requires moving all
    367 // existing digits down one to make space for the new one to be appended.
    368 //
    369 void
    370 DigitList::append(char digit)
    371 {
    372     U_ASSERT(digit>='0' && digit<='9');
    373     // Ignore digits which exceed the precision we can represent
    374     //    And don't fix for larger precision.  Fix callers instead.
    375     if (decNumberIsZero(fDecNumber)) {
    376         // Zero needs to be special cased because of the difference in the way
    377         // that the old DigitList and decNumber represent it.
    378         // digit cout was zero for digitList, is one for decNumber
    379         fDecNumber->lsu[0] = digit & 0x0f;
    380         fDecNumber->digits = 1;
    381         fDecNumber->exponent--;     // To match the old digit list implementation.
    382     } else {
    383         int32_t nDigits = fDecNumber->digits;
    384         if (nDigits < fContext.digits) {
    385             int i;
    386             for (i=nDigits; i>0; i--) {
    387                 fDecNumber->lsu[i] = fDecNumber->lsu[i-1];
    388             }
    389             fDecNumber->lsu[0] = digit & 0x0f;
    390             fDecNumber->digits++;
    391             // DigitList emulation - appending doesn't change the magnitude of existing
    392             //                       digits.  With decNumber's decimal being after the
    393             //                       least signficant digit, we need to adjust the exponent.
    394             fDecNumber->exponent--;
    395         }
    396     }
    397     internalClear();
    398 }
    399 
    400 char DigitList::getStrtodDecimalSeparator() {
    401     // TODO: maybe use andy's pthread once.
    402     static char gDecimal = 0;
    403     char result;
    404     {
    405         Mutex mutex;
    406         result = gDecimal;;
    407         if (result == 0) {
    408             // We need to know the decimal separator character that will be used with strtod().
    409             // Depends on the C runtime global locale.
    410             // Most commonly is '.'
    411             // TODO: caching could fail if the global locale is changed on the fly.
    412             char rep[MAX_DIGITS];
    413             sprintf(rep, "%+1.1f", 1.0);
    414             result = rep[2];
    415             gDecimal = result;;
    416         }
    417     }
    418     return result;
    419 }
    420 
    421 // -------------------------------------
    422 
    423 /**
    424  * Currently, getDouble() depends on strtod() to do its conversion.
    425  *
    426  * WARNING!!
    427  * This is an extremely costly function. ~1/2 of the conversion time
    428  * can be linked to this function.
    429  */
    430 double
    431 DigitList::getDouble() const
    432 {
    433     static char gDecimal = 0;
    434     char decimalSeparator;
    435     {
    436         Mutex mutex;
    437         if (fHave == kDouble) {
    438             return fUnion.fDouble;
    439         } else if(fHave == kInt64) {
    440             return (double)fUnion.fInt64;
    441         }
    442         decimalSeparator = gDecimal;
    443     }
    444 
    445     if (decimalSeparator == 0) {
    446         // We need to know the decimal separator character that will be used with strtod().
    447         // Depends on the C runtime global locale.
    448         // Most commonly is '.'
    449         // TODO: caching could fail if the global locale is changed on the fly.
    450         char rep[MAX_DIGITS];
    451         sprintf(rep, "%+1.1f", 1.0);
    452         decimalSeparator = rep[2];
    453     }
    454 
    455     double tDouble = 0.0;
    456     if (isZero()) {
    457         tDouble = 0.0;
    458         if (decNumberIsNegative(fDecNumber)) {
    459             tDouble /= -1;
    460         }
    461     } else if (isInfinite()) {
    462         if (std::numeric_limits<double>::has_infinity) {
    463             tDouble = std::numeric_limits<double>::infinity();
    464         } else {
    465             tDouble = std::numeric_limits<double>::max();
    466         }
    467         if (!isPositive()) {
    468             tDouble = -tDouble; //this was incorrectly "-fDouble" originally.
    469         }
    470     } else {
    471         MaybeStackArray<char, MAX_DBL_DIGITS+18> s;
    472            // Note:  14 is a  magic constant from the decNumber library documentation,
    473            //        the max number of extra characters beyond the number of digits
    474            //        needed to represent the number in string form.  Add a few more
    475            //        for the additional digits we retain.
    476 
    477         // Round down to appx. double precision, if the number is longer than that.
    478         // Copy the number first, so that we don't modify the original.
    479         if (getCount() > MAX_DBL_DIGITS + 3) {
    480             DigitList numToConvert(*this);
    481             numToConvert.reduce();    // Removes any trailing zeros, so that digit count is good.
    482             numToConvert.round(MAX_DBL_DIGITS+3);
    483             uprv_decNumberToString(numToConvert.fDecNumber, s.getAlias());
    484             // TODO:  how many extra digits should be included for an accurate conversion?
    485         } else {
    486             uprv_decNumberToString(this->fDecNumber, s.getAlias());
    487         }
    488         U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18);
    489 
    490         if (decimalSeparator != '.') {
    491             char *decimalPt = strchr(s.getAlias(), '.');
    492             if (decimalPt != NULL) {
    493                 *decimalPt = decimalSeparator;
    494             }
    495         }
    496         char *end = NULL;
    497         tDouble = uprv_strtod(s.getAlias(), &end);
    498     }
    499     {
    500         Mutex mutex;
    501         DigitList *nonConstThis = const_cast<DigitList *>(this);
    502         nonConstThis->internalSetDouble(tDouble);
    503         gDecimal = decimalSeparator;
    504     }
    505     return tDouble;
    506 }
    507 
    508 // -------------------------------------
    509 
    510 /**
    511  *  convert this number to an int32_t.   Round if there is a fractional part.
    512  *  Return zero if the number cannot be represented.
    513  */
    514 int32_t DigitList::getLong() /*const*/
    515 {
    516     int32_t result = 0;
    517     if (getUpperExponent() > 10) {
    518         // Overflow, absolute value too big.
    519         return result;
    520     }
    521     if (fDecNumber->exponent != 0) {
    522         // Force to an integer, with zero exponent, rounding if necessary.
    523         //   (decNumberToInt32 will only work if the exponent is exactly zero.)
    524         DigitList copy(*this);
    525         DigitList zero;
    526         uprv_decNumberQuantize(copy.fDecNumber, copy.fDecNumber, zero.fDecNumber, &fContext);
    527         result = uprv_decNumberToInt32(copy.fDecNumber, &fContext);
    528     } else {
    529         result = uprv_decNumberToInt32(fDecNumber, &fContext);
    530     }
    531     return result;
    532 }
    533 
    534 
    535 /**
    536  *  convert this number to an int64_t.   Truncate if there is a fractional part.
    537  *  Return zero if the number cannot be represented.
    538  */
    539 int64_t DigitList::getInt64() /*const*/ {
    540     if(fHave==kInt64) {
    541       return fUnion.fInt64;
    542     }
    543     // Truncate if non-integer.
    544     // Return 0 if out of range.
    545     // Range of in64_t is -9223372036854775808 to 9223372036854775807  (19 digits)
    546     //
    547     if (getUpperExponent() > 19) {
    548         // Overflow, absolute value too big.
    549         return 0;
    550     }
    551 
    552     // The number of integer digits may differ from the number of digits stored
    553     //   in the decimal number.
    554     //     for 12.345  numIntDigits = 2, number->digits = 5
    555     //     for 12E4    numIntDigits = 6, number->digits = 2
    556     // The conversion ignores the fraction digits in the first case,
    557     // and fakes up extra zero digits in the second.
    558     // TODO:  It would be faster to store a table of powers of ten to multiply by
    559     //        instead of looping over zero digits, multiplying each time.
    560 
    561     int32_t numIntDigits = getUpperExponent();
    562     uint64_t value = 0;
    563     for (int32_t i = 0; i < numIntDigits; i++) {
    564         // Loop is iterating over digits starting with the most significant.
    565         // Numbers are stored with the least significant digit at index zero.
    566         int32_t digitIndex = fDecNumber->digits - i - 1;
    567         int32_t v = (digitIndex >= 0) ? fDecNumber->lsu[digitIndex] : 0;
    568         value = value * (uint64_t)10 + (uint64_t)v;
    569     }
    570 
    571     if (decNumberIsNegative(fDecNumber)) {
    572         value = ~value;
    573         value += 1;
    574     }
    575     int64_t svalue = (int64_t)value;
    576 
    577     // Check overflow.  It's convenient that the MSD is 9 only on overflow, the amount of
    578     //                  overflow can't wrap too far.  The test will also fail -0, but
    579     //                  that does no harm; the right answer is 0.
    580     if (numIntDigits == 19) {
    581         if (( decNumberIsNegative(fDecNumber) && svalue>0) ||
    582             (!decNumberIsNegative(fDecNumber) && svalue<0)) {
    583             svalue = 0;
    584         }
    585     }
    586 
    587     return svalue;
    588 }
    589 
    590 
    591 /**
    592  *  Return a string form of this number.
    593  *     Format is as defined by the decNumber library, for interchange of
    594  *     decimal numbers.
    595  */
    596 void DigitList::getDecimal(CharString &str, UErrorCode &status) {
    597     if (U_FAILURE(status)) {
    598         return;
    599     }
    600 
    601     // A decimal number in string form can, worst case, be 14 characters longer
    602     //  than the number of digits.  So says the decNumber library doc.
    603     int32_t maxLength = fDecNumber->digits + 14;
    604     int32_t capacity = 0;
    605     char *buffer = str.clear().getAppendBuffer(maxLength, 0, capacity, status);
    606     if (U_FAILURE(status)) {
    607         return;    // Memory allocation error on growing the string.
    608     }
    609     U_ASSERT(capacity >= maxLength);
    610     uprv_decNumberToString(this->fDecNumber, buffer);
    611     U_ASSERT((int32_t)uprv_strlen(buffer) <= maxLength);
    612     str.append(buffer, -1, status);
    613 }
    614 
    615 /**
    616  * Return true if this is an integer value that can be held
    617  * by an int32_t type.
    618  */
    619 UBool
    620 DigitList::fitsIntoLong(UBool ignoreNegativeZero) /*const*/
    621 {
    622     if (decNumberIsSpecial(this->fDecNumber)) {
    623         // NaN or Infinity.  Does not fit in int32.
    624         return FALSE;
    625     }
    626     uprv_decNumberTrim(this->fDecNumber);
    627     if (fDecNumber->exponent < 0) {
    628         // Number contains fraction digits.
    629         return FALSE;
    630     }
    631     if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero &&
    632         (fDecNumber->bits & DECNEG) != 0) {
    633         // Negative Zero, not ingored.  Cannot represent as a long.
    634         return FALSE;
    635     }
    636     if (getUpperExponent() < 10) {
    637         // The number is 9 or fewer digits.
    638         // The max and min int32 are 10 digts, so this number fits.
    639         // This is the common case.
    640         return TRUE;
    641     }
    642 
    643     // TODO:  Should cache these constants; construction is relatively costly.
    644     //        But not of huge consequence; they're only needed for 10 digit ints.
    645     UErrorCode status = U_ZERO_ERROR;
    646     DigitList min32; min32.set("-2147483648", status);
    647     if (this->compare(min32) < 0) {
    648         return FALSE;
    649     }
    650     DigitList max32; max32.set("2147483647", status);
    651     if (this->compare(max32) > 0) {
    652         return FALSE;
    653     }
    654     if (U_FAILURE(status)) {
    655         return FALSE;
    656     }
    657     return true;
    658 }
    659 
    660 
    661 
    662 /**
    663  * Return true if the number represented by this object can fit into
    664  * a long.
    665  */
    666 UBool
    667 DigitList::fitsIntoInt64(UBool ignoreNegativeZero) /*const*/
    668 {
    669     if (decNumberIsSpecial(this->fDecNumber)) {
    670         // NaN or Infinity.  Does not fit in int32.
    671         return FALSE;
    672     }
    673     uprv_decNumberTrim(this->fDecNumber);
    674     if (fDecNumber->exponent < 0) {
    675         // Number contains fraction digits.
    676         return FALSE;
    677     }
    678     if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero &&
    679         (fDecNumber->bits & DECNEG) != 0) {
    680         // Negative Zero, not ingored.  Cannot represent as a long.
    681         return FALSE;
    682     }
    683     if (getUpperExponent() < 19) {
    684         // The number is 18 or fewer digits.
    685         // The max and min int64 are 19 digts, so this number fits.
    686         // This is the common case.
    687         return TRUE;
    688     }
    689 
    690     // TODO:  Should cache these constants; construction is relatively costly.
    691     //        But not of huge consequence; they're only needed for 19 digit ints.
    692     UErrorCode status = U_ZERO_ERROR;
    693     DigitList min64; min64.set("-9223372036854775808", status);
    694     if (this->compare(min64) < 0) {
    695         return FALSE;
    696     }
    697     DigitList max64; max64.set("9223372036854775807", status);
    698     if (this->compare(max64) > 0) {
    699         return FALSE;
    700     }
    701     if (U_FAILURE(status)) {
    702         return FALSE;
    703     }
    704     return true;
    705 }
    706 
    707 
    708 // -------------------------------------
    709 
    710 void
    711 DigitList::set(int32_t source)
    712 {
    713     set((int64_t)source);
    714     internalSetDouble(source);
    715 }
    716 
    717 // -------------------------------------
    718 /**
    719  * Set an int64, via decnumber
    720  */
    721 void
    722 DigitList::set(int64_t source)
    723 {
    724     char str[MAX_DIGITS+2];   // Leave room for sign and trailing nul.
    725     formatBase10(source, str);
    726     U_ASSERT(uprv_strlen(str) < sizeof(str));
    727 
    728     uprv_decNumberFromString(fDecNumber, str, &fContext);
    729     internalSetDouble(static_cast<double>(source));
    730 }
    731 
    732 /**
    733  * Set an int64, with no decnumber
    734  */
    735 void
    736 DigitList::setInteger(int64_t source)
    737 {
    738   fDecNumber=NULL;
    739   internalSetInt64(source);
    740 }
    741 
    742 
    743 // -------------------------------------
    744 /**
    745  * Set the DigitList from a decimal number string.
    746  *
    747  * The incoming string _must_ be nul terminated, even though it is arriving
    748  * as a StringPiece because that is what the decNumber library wants.
    749  * We can get away with this for an internal function; it would not
    750  * be acceptable for a public API.
    751  */
    752 void
    753 DigitList::set(const StringPiece &source, UErrorCode &status, uint32_t /*fastpathBits*/) {
    754     if (U_FAILURE(status)) {
    755         return;
    756     }
    757 
    758 #if 0
    759     if(fastpathBits==(kFastpathOk|kNoDecimal)) {
    760       int32_t size = source.size();
    761       const char *data = source.data();
    762       int64_t r = 0;
    763       int64_t m = 1;
    764       // fast parse
    765       while(size>0) {
    766         char ch = data[--size];
    767         if(ch=='+') {
    768           break;
    769         } else if(ch=='-') {
    770           r = -r;
    771           break;
    772         } else {
    773           int64_t d = ch-'0';
    774           //printf("CH[%d]=%c, %d, *=%d\n", size,ch, (int)d, (int)m);
    775           r+=(d)*m;
    776           m *= 10;
    777         }
    778       }
    779       //printf("R=%d\n", r);
    780       set(r);
    781     } else
    782 #endif
    783         {
    784       // Figure out a max number of digits to use during the conversion, and
    785       // resize the number up if necessary.
    786       int32_t numDigits = source.length();
    787       if (numDigits > fContext.digits) {
    788         // fContext.digits == fStorage.getCapacity()
    789         decNumber *t = fStorage.resize(numDigits, fStorage.getCapacity());
    790         if (t == NULL) {
    791           status = U_MEMORY_ALLOCATION_ERROR;
    792           return;
    793         }
    794         fDecNumber = t;
    795         fContext.digits = numDigits;
    796       }
    797 
    798       fContext.status = 0;
    799       uprv_decNumberFromString(fDecNumber, source.data(), &fContext);
    800       if ((fContext.status & DEC_Conversion_syntax) != 0) {
    801         status = U_DECIMAL_NUMBER_SYNTAX_ERROR;
    802       }
    803     }
    804     internalClear();
    805 }
    806 
    807 /**
    808  * Set the digit list to a representation of the given double value.
    809  * This method supports both fixed-point and exponential notation.
    810  * @param source Value to be converted.
    811  */
    812 void
    813 DigitList::set(double source)
    814 {
    815     // for now, simple implementation; later, do proper IEEE stuff
    816     char rep[MAX_DIGITS + 8]; // Extra space for '+', '.', e+NNN, and '\0' (actually +8 is enough)
    817 
    818     // Generate a representation of the form /[+-][0-9].[0-9]+e[+-][0-9]+/
    819     // Can also generate /[+-]nan/ or /[+-]inf/
    820     // TODO: Use something other than sprintf() here, since it's behavior is somewhat platform specific.
    821     //       That is why infinity is special cased here.
    822     if (uprv_isInfinite(source)) {
    823         if (uprv_isNegativeInfinity(source)) {
    824             uprv_strcpy(rep,"-inf"); // Handle negative infinity
    825         } else {
    826             uprv_strcpy(rep,"inf");
    827         }
    828     } else {
    829         sprintf(rep, "%+1.*e", MAX_DBL_DIGITS - 1, source);
    830     }
    831     U_ASSERT(uprv_strlen(rep) < sizeof(rep));
    832 
    833     // uprv_decNumberFromString() will parse the string expecting '.' as a
    834     // decimal separator, however sprintf() can use ',' in certain locales.
    835     // Overwrite a ',' with '.' here before proceeding.
    836     char *decimalSeparator = strchr(rep, ',');
    837     if (decimalSeparator != NULL) {
    838         *decimalSeparator = '.';
    839     }
    840 
    841     // Create a decNumber from the string.
    842     uprv_decNumberFromString(fDecNumber, rep, &fContext);
    843     uprv_decNumberTrim(fDecNumber);
    844     internalSetDouble(source);
    845 }
    846 
    847 // -------------------------------------
    848 
    849 /*
    850  * Multiply
    851  *      The number will be expanded if need be to retain full precision.
    852  *      In practice, for formatting, multiply is by 10, 100 or 1000, so more digits
    853  *      will not be required for this use.
    854  */
    855 void
    856 DigitList::mult(const DigitList &other, UErrorCode &status) {
    857     if (U_FAILURE(status)) {
    858         return;
    859     }
    860     fContext.status = 0;
    861     int32_t requiredDigits = this->digits() + other.digits();
    862     if (requiredDigits > fContext.digits) {
    863         reduce();    // Remove any trailing zeros
    864         int32_t requiredDigits = this->digits() + other.digits();
    865         ensureCapacity(requiredDigits, status);
    866     }
    867     uprv_decNumberMultiply(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
    868     internalClear();
    869 }
    870 
    871 // -------------------------------------
    872 
    873 /*
    874  * Divide
    875  *      The number will _not_ be expanded for inexact results.
    876  *      TODO:  probably should expand some, for rounding increments that
    877  *             could add a few digits, e.g. .25, but not expand arbitrarily.
    878  */
    879 void
    880 DigitList::div(const DigitList &other, UErrorCode &status) {
    881     if (U_FAILURE(status)) {
    882         return;
    883     }
    884     uprv_decNumberDivide(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
    885     internalClear();
    886 }
    887 
    888 // -------------------------------------
    889 
    890 /*
    891  * ensureCapacity.   Grow the digit storage for the number if it's less than the requested
    892  *         amount.  Never reduce it.  Available size is kept in fContext.digits.
    893  */
    894 void
    895 DigitList::ensureCapacity(int32_t requestedCapacity, UErrorCode &status) {
    896     if (U_FAILURE(status)) {
    897         return;
    898     }
    899     if (requestedCapacity <= 0) {
    900         status = U_ILLEGAL_ARGUMENT_ERROR;
    901         return;
    902     }
    903     if (requestedCapacity > DEC_MAX_DIGITS) {
    904         // Don't report an error for requesting too much.
    905         // Arithemetic Results will be rounded to what can be supported.
    906         //   At 999,999,999 max digits, exceeding the limit is not too likely!
    907         requestedCapacity = DEC_MAX_DIGITS;
    908     }
    909     if (requestedCapacity > fContext.digits) {
    910         decNumber *newBuffer = fStorage.resize(requestedCapacity, fStorage.getCapacity());
    911         if (newBuffer == NULL) {
    912             status = U_MEMORY_ALLOCATION_ERROR;
    913             return;
    914         }
    915         fContext.digits = requestedCapacity;
    916         fDecNumber = newBuffer;
    917     }
    918 }
    919 
    920 // -------------------------------------
    921 
    922 /**
    923  * Round the representation to the given number of digits.
    924  * @param maximumDigits The maximum number of digits to be shown.
    925  * Upon return, count will be less than or equal to maximumDigits.
    926  */
    927 void
    928 DigitList::round(int32_t maximumDigits)
    929 {
    930     reduce();
    931     if (maximumDigits >= fDecNumber->digits) {
    932         return;
    933     }
    934     int32_t savedDigits  = fContext.digits;
    935     fContext.digits = maximumDigits;
    936     uprv_decNumberPlus(fDecNumber, fDecNumber, &fContext);
    937     fContext.digits = savedDigits;
    938     uprv_decNumberTrim(fDecNumber);
    939     reduce();
    940     internalClear();
    941 }
    942 
    943 
    944 void
    945 DigitList::roundFixedPoint(int32_t maximumFractionDigits) {
    946     reduce();        // Remove trailing zeros.
    947     if (fDecNumber->exponent >= -maximumFractionDigits) {
    948         return;
    949     }
    950     decNumber scale;   // Dummy decimal number, but with the desired number of
    951     uprv_decNumberZero(&scale);    //    fraction digits.
    952     scale.exponent = -maximumFractionDigits;
    953     scale.lsu[0] = 1;
    954 
    955     uprv_decNumberQuantize(fDecNumber, fDecNumber, &scale, &fContext);
    956     reduce();
    957     internalClear();
    958 }
    959 
    960 // -------------------------------------
    961 
    962 void
    963 DigitList::toIntegralValue() {
    964     uprv_decNumberToIntegralValue(fDecNumber, fDecNumber, &fContext);
    965 }
    966 
    967 
    968 // -------------------------------------
    969 UBool
    970 DigitList::isZero() const
    971 {
    972     return decNumberIsZero(fDecNumber);
    973 }
    974 
    975 // -------------------------------------
    976 int32_t
    977 DigitList::getUpperExponent() const {
    978     return fDecNumber->digits + fDecNumber->exponent;
    979 }
    980 
    981 DigitInterval &
    982 DigitList::getSmallestInterval(DigitInterval &result) const {
    983     result.setLeastSignificantInclusive(fDecNumber->exponent);
    984     result.setMostSignificantExclusive(getUpperExponent());
    985     return result;
    986 }
    987 
    988 uint8_t
    989 DigitList::getDigitByExponent(int32_t exponent) const {
    990     int32_t idx = exponent - fDecNumber->exponent;
    991     if (idx < 0 || idx >= fDecNumber->digits) {
    992         return 0;
    993     }
    994     return fDecNumber->lsu[idx];
    995 }
    996 
    997 void
    998 DigitList::appendDigitsTo(CharString &str, UErrorCode &status) const {
    999     str.append((const char *) fDecNumber->lsu, fDecNumber->digits, status);
   1000 }
   1001 
   1002 void
   1003 DigitList::roundAtExponent(int32_t exponent, int32_t maxSigDigits) {
   1004     reduce();
   1005     if (maxSigDigits < fDecNumber->digits) {
   1006         int32_t minExponent = getUpperExponent() - maxSigDigits;
   1007         if (exponent < minExponent) {
   1008             exponent = minExponent;
   1009         }
   1010     }
   1011     if (exponent <= fDecNumber->exponent) {
   1012         return;
   1013     }
   1014     int32_t digits = getUpperExponent() - exponent;
   1015     if (digits > 0) {
   1016         round(digits);
   1017     } else {
   1018         roundFixedPoint(-exponent);
   1019     }
   1020 }
   1021 
   1022 void
   1023 DigitList::quantize(const DigitList &quantity, UErrorCode &status) {
   1024     if (U_FAILURE(status)) {
   1025         return;
   1026     }
   1027     div(quantity, status);
   1028     roundAtExponent(0);
   1029     mult(quantity, status);
   1030     reduce();
   1031 }
   1032 
   1033 int32_t
   1034 DigitList::getScientificExponent(
   1035         int32_t minIntDigitCount, int32_t exponentMultiplier) const {
   1036     // The exponent for zero is always zero.
   1037     if (isZero()) {
   1038         return 0;
   1039     }
   1040     int32_t intDigitCount = getUpperExponent();
   1041     int32_t exponent;
   1042     if (intDigitCount >= minIntDigitCount) {
   1043         int32_t maxAdjustment = intDigitCount - minIntDigitCount;
   1044         exponent = (maxAdjustment / exponentMultiplier) * exponentMultiplier;
   1045     } else {
   1046         int32_t minAdjustment = minIntDigitCount - intDigitCount;
   1047         exponent = ((minAdjustment + exponentMultiplier - 1) / exponentMultiplier) * -exponentMultiplier;
   1048     }
   1049     return exponent;
   1050 }
   1051 
   1052 int32_t
   1053 DigitList::toScientific(
   1054         int32_t minIntDigitCount, int32_t exponentMultiplier) {
   1055     int32_t exponent = getScientificExponent(
   1056             minIntDigitCount, exponentMultiplier);
   1057     shiftDecimalRight(-exponent);
   1058     return exponent;
   1059 }
   1060 
   1061 void
   1062 DigitList::shiftDecimalRight(int32_t n) {
   1063     fDecNumber->exponent += n;
   1064     internalClear();
   1065 }
   1066 
   1067 U_NAMESPACE_END
   1068 #endif // #if !UCONFIG_NO_FORMATTING
   1069 
   1070 //eof
   1071