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