LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - digitlst.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 424 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 49 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // © 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
      64             : # if U_PLATFORM_USES_ONLY_WIN32_API || 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           0 : DigitList::DigitList()
      95             : {
      96           0 :     uprv_decContextDefault(&fContext, DEC_INIT_BASE);
      97           0 :     fContext.traps  = 0;
      98           0 :     uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN);
      99           0 :     fContext.digits = fStorage.getCapacity();
     100             : 
     101           0 :     fDecNumber = fStorage.getAlias();
     102           0 :     uprv_decNumberZero(fDecNumber);
     103             : 
     104           0 :     internalSetDouble(0.0);
     105           0 : }
     106             : 
     107             : // -------------------------------------
     108             : 
     109           0 : DigitList::~DigitList()
     110             : {
     111           0 : }
     112             : 
     113             : // -------------------------------------
     114             : // copy constructor
     115             : 
     116           0 : DigitList::DigitList(const DigitList &other)
     117             : {
     118           0 :     fDecNumber = fStorage.getAlias();
     119           0 :     *this = other;
     120           0 : }
     121             : 
     122             : 
     123             : // -------------------------------------
     124             : // assignment operator
     125             : 
     126             : DigitList&
     127           0 : DigitList::operator=(const DigitList& other)
     128             : {
     129           0 :     if (this != &other)
     130             :     {
     131           0 :         uprv_memcpy(&fContext, &other.fContext, sizeof(decContext));
     132             : 
     133           0 :         if (other.fStorage.getCapacity() > fStorage.getCapacity()) {
     134           0 :             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           0 :         fContext.digits = fStorage.getCapacity();
     139           0 :         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           0 :             Mutex mutex;
     146             : 
     147           0 :             if(other.fHave==kDouble) {
     148           0 :                 fUnion.fDouble = other.fUnion.fDouble;
     149             :             }
     150           0 :             fHave = other.fHave;
     151             :         }
     152             :     }
     153           0 :     return *this;
     154             : }
     155             : 
     156             : // -------------------------------------
     157             : //    operator ==  (does not exactly match the old DigitList function)
     158             : 
     159             : UBool
     160           0 : DigitList::operator==(const DigitList& that) const
     161             : {
     162           0 :     if (this == &that) {
     163           0 :         return TRUE;
     164             :     }
     165             :     decNumber n;  // Has space for only a none digit value.
     166             :     decContext c;
     167           0 :     uprv_decContextDefault(&c, DEC_INIT_BASE);
     168           0 :     c.digits = 1;
     169           0 :     c.traps = 0;
     170             : 
     171           0 :     uprv_decNumberCompare(&n, this->fDecNumber, that.fDecNumber, &c);
     172           0 :     UBool result = decNumberIsZero(&n);
     173           0 :     return result;
     174             : }
     175             : 
     176             : // -------------------------------------
     177             : //      comparison function.   Returns 
     178             : //         Not Comparable :  -2
     179             : //                      < :  -1
     180             : //                     == :   0
     181             : //                      > :  +1
     182           0 : int32_t DigitList::compare(const DigitList &other) {
     183             :     decNumber   result;
     184           0 :     int32_t     savedDigits = fContext.digits;
     185           0 :     fContext.digits = 1;
     186           0 :     uprv_decNumberCompare(&result, this->fDecNumber, other.fDecNumber, &fContext);
     187           0 :     fContext.digits = savedDigits;
     188           0 :     if (decNumberIsZero(&result)) {
     189           0 :         return 0;
     190           0 :     } else if (decNumberIsSpecial(&result)) {
     191           0 :         return -2;
     192           0 :     } else if (result.bits & DECNEG) {
     193           0 :         return -1;
     194             :     } else {
     195           0 :         return 1;
     196             :     }
     197             : }
     198             : 
     199             : 
     200             : // -------------------------------------
     201             : //  Reduce - remove trailing zero digits.
     202             : void
     203           0 : DigitList::reduce() {
     204           0 :     uprv_decNumberReduce(fDecNumber, fDecNumber, &fContext);
     205           0 : }
     206             : 
     207             : 
     208             : // -------------------------------------
     209             : //  trim - remove trailing fraction zero digits.
     210             : void
     211           0 : DigitList::trim() {
     212           0 :     uprv_decNumberTrim(fDecNumber);
     213           0 : }
     214             : 
     215             : // -------------------------------------
     216             : // Resets the digit list; sets all the digits to zero.
     217             : 
     218             : void
     219           0 : DigitList::clear()
     220             : {
     221           0 :     uprv_decNumberZero(fDecNumber);
     222           0 :     uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN);
     223           0 :     internalSetDouble(0.0);
     224           0 : }
     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           0 : 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           0 :     const int32_t MAX_IDX = MAX_DIGITS+2;
     241           0 :     int32_t destIdx = MAX_IDX;
     242           0 :     outputStr[--destIdx] = 0; 
     243             : 
     244           0 :     int64_t  n = number;
     245           0 :     if (number < 0) {   // Negative numbers are slightly larger than a postive
     246           0 :         outputStr[--destIdx] = (char)(-(n % 10) + kZero);
     247           0 :         n /= -10;
     248             :     }
     249           0 :     do { 
     250           0 :         outputStr[--destIdx] = (char)(n % 10 + kZero);
     251           0 :         n /= 10;
     252           0 :     } while (n > 0);
     253             :     
     254           0 :     if (number < 0) {
     255           0 :         outputStr[--destIdx] = '-';
     256             :     }
     257             : 
     258             :     // Slide the number to the start of the output str
     259           0 :     U_ASSERT(destIdx >= 0);
     260           0 :     int32_t length = MAX_IDX - destIdx;
     261           0 :     uprv_memmove(outputStr, outputStr+MAX_IDX-length, length);
     262             : 
     263           0 :     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           0 : DigitList::setRoundingMode(DecimalFormat::ERoundingMode m) {
     280             :     enum rounding r;
     281             : 
     282           0 :     switch (m) {
     283           0 :       case  DecimalFormat::kRoundCeiling:  r = DEC_ROUND_CEILING;   break;
     284           0 :       case  DecimalFormat::kRoundFloor:    r = DEC_ROUND_FLOOR;     break;
     285           0 :       case  DecimalFormat::kRoundDown:     r = DEC_ROUND_DOWN;      break;
     286           0 :       case  DecimalFormat::kRoundUp:       r = DEC_ROUND_UP;        break;
     287           0 :       case  DecimalFormat::kRoundHalfEven: r = DEC_ROUND_HALF_EVEN; break;
     288           0 :       case  DecimalFormat::kRoundHalfDown: r = DEC_ROUND_HALF_DOWN; break;
     289           0 :       case  DecimalFormat::kRoundHalfUp:   r = DEC_ROUND_HALF_UP;   break;
     290           0 :       case  DecimalFormat::kRoundUnnecessary: r = DEC_ROUND_HALF_EVEN; break;
     291             :       default:
     292             :          // TODO: how to report the problem?
     293             :          // Leave existing mode unchanged.
     294           0 :          r = uprv_decContextGetRounding(&fContext);
     295             :     }
     296           0 :     uprv_decContextSetRounding(&fContext, r);
     297             :   
     298           0 : }
     299             : 
     300             : 
     301             : // -------------------------------------
     302             : 
     303             : void  
     304           0 : DigitList::setPositive(UBool s) {
     305           0 :     if (s) {
     306           0 :         fDecNumber->bits &= ~DECNEG; 
     307             :     } else {
     308           0 :         fDecNumber->bits |= DECNEG;
     309             :     }
     310           0 :     internalClear();
     311           0 : }
     312             : // -------------------------------------
     313             : 
     314             : void     
     315           0 : DigitList::setDecimalAt(int32_t d) {
     316           0 :     U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0);  // Not Infinity or NaN
     317           0 :     U_ASSERT(d-1>-999999999);
     318           0 :     U_ASSERT(d-1< 999999999);
     319           0 :     int32_t adjustedDigits = fDecNumber->digits;
     320           0 :     if (decNumberIsZero(fDecNumber)) {
     321             :         // Account for difference in how zero is represented between DigitList & decNumber.
     322           0 :         adjustedDigits = 0;
     323             :     }
     324           0 :     fDecNumber->exponent = d - adjustedDigits;
     325           0 :     internalClear();
     326           0 : }
     327             : 
     328             : int32_t  
     329           0 : DigitList::getDecimalAt() {
     330           0 :     U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0);  // Not Infinity or NaN
     331           0 :     if (decNumberIsZero(fDecNumber) || ((fDecNumber->bits & DECSPECIAL) != 0)) {
     332           0 :         return fDecNumber->exponent;  // Exponent should be zero for these cases.
     333             :     }
     334           0 :     return fDecNumber->exponent + fDecNumber->digits;
     335             : }
     336             : 
     337             : void     
     338           0 : DigitList::setCount(int32_t c)  {
     339           0 :     U_ASSERT(c <= fContext.digits);
     340           0 :     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           0 :         c = 1;
     344           0 :         fDecNumber->lsu[0] = 0;
     345             :     }
     346           0 :     fDecNumber->digits = c;
     347           0 :     internalClear();
     348           0 : }
     349             : 
     350             : int32_t  
     351           0 : DigitList::getCount() const {
     352           0 :     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           0 :        return 0;
     356             :     } else {
     357           0 :        return fDecNumber->digits;
     358             :     }
     359             : }
     360             :     
     361             : void     
     362           0 : DigitList::setDigit(int32_t i, char v) {
     363           0 :     int32_t count = fDecNumber->digits;
     364           0 :     U_ASSERT(i<count);
     365           0 :     U_ASSERT(v>='0' && v<='9');
     366           0 :     v &= 0x0f;
     367           0 :     fDecNumber->lsu[count-i-1] = v;
     368           0 :     internalClear();
     369           0 : }
     370             : 
     371             : char     
     372           0 : DigitList::getDigit(int32_t i) {
     373           0 :     int32_t count = fDecNumber->digits;
     374           0 :     U_ASSERT(i<count);
     375           0 :     return fDecNumber->lsu[count-i-1] + '0';
     376             : }
     377             : 
     378             : // copied from DigitList::getDigit()
     379             : uint8_t
     380           0 : DigitList::getDigitValue(int32_t i) {
     381           0 :     int32_t count = fDecNumber->digits;
     382           0 :     U_ASSERT(i<count);
     383           0 :     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           0 : DigitList::append(char digit)
     396             : {
     397           0 :     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           0 :     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           0 :         fDecNumber->lsu[0] = digit & 0x0f;
     405           0 :         fDecNumber->digits = 1;
     406           0 :         fDecNumber->exponent--;     // To match the old digit list implementation.
     407             :     } else {
     408           0 :         int32_t nDigits = fDecNumber->digits;
     409           0 :         if (nDigits < fContext.digits) {
     410             :             int i;
     411           0 :             for (i=nDigits; i>0; i--) {
     412           0 :                 fDecNumber->lsu[i] = fDecNumber->lsu[i-1];
     413             :             }
     414           0 :             fDecNumber->lsu[0] = digit & 0x0f;
     415           0 :             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           0 :             fDecNumber->exponent--;
     420             :         }
     421             :     }
     422           0 :     internalClear();
     423           0 : }
     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           0 : DigitList::getDouble() const
     436             : {
     437             :     {
     438           0 :         Mutex mutex;
     439           0 :         if (fHave == kDouble) {
     440           0 :             return fUnion.fDouble;
     441             :         }
     442             :     }
     443             : 
     444           0 :     double tDouble = 0.0;
     445           0 :     if (isZero()) {
     446           0 :         tDouble = 0.0;
     447           0 :         if (decNumberIsNegative(fDecNumber)) {
     448           0 :             tDouble /= -1;
     449             :         }
     450           0 :     } else if (isInfinite()) {
     451             :         if (std::numeric_limits<double>::has_infinity) {
     452           0 :             tDouble = std::numeric_limits<double>::infinity();
     453             :         } else {
     454             :             tDouble = std::numeric_limits<double>::max();
     455             :         }
     456           0 :         if (!isPositive()) {
     457           0 :             tDouble = -tDouble; //this was incorrectly "-fDouble" originally.
     458             :         } 
     459             :     } else {
     460           0 :         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           0 :         if (getCount() > MAX_DBL_DIGITS + 3) {
     469           0 :             DigitList numToConvert(*this);
     470           0 :             numToConvert.reduce();    // Removes any trailing zeros, so that digit count is good.
     471           0 :             numToConvert.round(MAX_DBL_DIGITS+3);
     472           0 :             uprv_decNumberToString(numToConvert.fDecNumber, s.getAlias());
     473             :             // TODO:  how many extra digits should be included for an accurate conversion?
     474             :         } else {
     475           0 :             uprv_decNumberToString(this->fDecNumber, s.getAlias());
     476             :         }
     477           0 :         U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18);
     478             : 
     479           0 :         char *end = NULL;
     480           0 :         tDouble = decimalStrToDouble(s.getAlias(), &end);
     481             :     }
     482             :     {
     483           0 :         Mutex mutex;
     484           0 :         DigitList *nonConstThis = const_cast<DigitList *>(this);
     485           0 :         nonConstThis->internalSetDouble(tDouble);
     486             :     }
     487           0 :     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           0 : 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           0 :     return TRUE;
     511             : }
     512             : // C Locale initialization func
     513           0 : static void U_CALLCONV initCLocale(void) {
     514           0 :     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           0 : }
     523             : U_CDECL_END
     524             : 
     525             : double
     526           0 : DigitList::decimalStrToDouble(char *decstr, char **end) {
     527           0 :     umtx_initOnce(gCLocaleInitOnce, &initCLocale);
     528             : #if U_USE_STRTOD_L
     529             :     return strtod_l(decstr, end, gCLocale);
     530             : #else
     531           0 :     char *decimalPt = strchr(decstr, '.');
     532           0 :     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           0 :         sprintf(rep, "%+1.1f", 1.0);
     538           0 :         *decimalPt = rep[2];
     539             :     }
     540           0 :     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           0 : int32_t DigitList::getLong() /*const*/
     551             : {
     552           0 :     int32_t result = 0;
     553           0 :     if (getUpperExponent() > 10) { 
     554             :         // Overflow, absolute value too big.
     555           0 :         return result;
     556             :     }
     557           0 :     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           0 :         DigitList copy(*this);
     561           0 :         DigitList zero;
     562           0 :         uprv_decNumberQuantize(copy.fDecNumber, copy.fDecNumber, zero.fDecNumber, &fContext);
     563           0 :         result = uprv_decNumberToInt32(copy.fDecNumber, &fContext);
     564             :     } else {
     565           0 :         result = uprv_decNumberToInt32(fDecNumber, &fContext);
     566             :     }
     567           0 :     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           0 : 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           0 :     if (getUpperExponent() > 19) { 
     583             :         // Overflow, absolute value too big.
     584           0 :         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           0 :     int32_t numIntDigits = getUpperExponent(); 
     597           0 :     uint64_t value = 0;
     598           0 :     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           0 :         int32_t digitIndex = fDecNumber->digits - i - 1;
     602           0 :         int32_t v = (digitIndex >= 0) ? fDecNumber->lsu[digitIndex] : 0;
     603           0 :         value = value * (uint64_t)10 + (uint64_t)v;
     604             :     }
     605             : 
     606           0 :     if (decNumberIsNegative(fDecNumber)) {
     607           0 :         value = ~value;
     608           0 :         value += 1;
     609             :     }
     610           0 :     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           0 :     if (numIntDigits == 19) {
     616           0 :         if (( decNumberIsNegative(fDecNumber) && svalue>0) ||
     617           0 :             (!decNumberIsNegative(fDecNumber) && svalue<0)) {
     618           0 :             svalue = 0;
     619             :         }
     620             :     }
     621             :         
     622           0 :     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           0 : void DigitList::getDecimal(CharString &str, UErrorCode &status) {
     632           0 :     if (U_FAILURE(status)) {
     633           0 :         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           0 :     int32_t maxLength = fDecNumber->digits + 14;
     639           0 :     int32_t capacity = 0;
     640           0 :     char *buffer = str.clear().getAppendBuffer(maxLength, 0, capacity, status);
     641           0 :     if (U_FAILURE(status)) {
     642           0 :         return;    // Memory allocation error on growing the string.
     643             :     }
     644           0 :     U_ASSERT(capacity >= maxLength);
     645           0 :     uprv_decNumberToString(this->fDecNumber, buffer);
     646           0 :     U_ASSERT((int32_t)uprv_strlen(buffer) <= maxLength);
     647           0 :     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           0 : DigitList::fitsIntoLong(UBool ignoreNegativeZero) /*const*/
     656             : {
     657           0 :     if (decNumberIsSpecial(this->fDecNumber)) {
     658             :         // NaN or Infinity.  Does not fit in int32.
     659           0 :         return FALSE;
     660             :     }
     661           0 :     uprv_decNumberTrim(this->fDecNumber);
     662           0 :     if (fDecNumber->exponent < 0) {
     663             :         // Number contains fraction digits.
     664           0 :         return FALSE;
     665             :     }
     666           0 :     if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero &&
     667           0 :         (fDecNumber->bits & DECNEG) != 0) {
     668             :         // Negative Zero, not ingored.  Cannot represent as a long.
     669           0 :         return FALSE;
     670             :     }
     671           0 :     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           0 :         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           0 :     UErrorCode status = U_ZERO_ERROR;
     681           0 :     DigitList min32; min32.set("-2147483648", status);
     682           0 :     if (this->compare(min32) < 0) {
     683           0 :         return FALSE;
     684             :     }
     685           0 :     DigitList max32; max32.set("2147483647", status);
     686           0 :     if (this->compare(max32) > 0) {
     687           0 :         return FALSE;
     688             :     }
     689           0 :     if (U_FAILURE(status)) {
     690           0 :         return FALSE;
     691             :     }
     692           0 :     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           0 : DigitList::fitsIntoInt64(UBool ignoreNegativeZero) /*const*/
     703             : {
     704           0 :     if (decNumberIsSpecial(this->fDecNumber)) {
     705             :         // NaN or Infinity.  Does not fit in int32.
     706           0 :         return FALSE;
     707             :     }
     708           0 :     uprv_decNumberTrim(this->fDecNumber);
     709           0 :     if (fDecNumber->exponent < 0) {
     710             :         // Number contains fraction digits.
     711           0 :         return FALSE;
     712             :     }
     713           0 :     if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero &&
     714           0 :         (fDecNumber->bits & DECNEG) != 0) {
     715             :         // Negative Zero, not ingored.  Cannot represent as a long.
     716           0 :         return FALSE;
     717             :     }
     718           0 :     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           0 :         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           0 :     UErrorCode status = U_ZERO_ERROR;
     728           0 :     DigitList min64; min64.set("-9223372036854775808", status);
     729           0 :     if (this->compare(min64) < 0) {
     730           0 :         return FALSE;
     731             :     }
     732           0 :     DigitList max64; max64.set("9223372036854775807", status);
     733           0 :     if (this->compare(max64) > 0) {
     734           0 :         return FALSE;
     735             :     }
     736           0 :     if (U_FAILURE(status)) {
     737           0 :         return FALSE;
     738             :     }
     739           0 :     return true;
     740             : }
     741             : 
     742             : 
     743             : // -------------------------------------
     744             : 
     745             : void
     746           0 : DigitList::set(int32_t source)
     747             : {
     748           0 :     set((int64_t)source);
     749           0 :     internalSetDouble(source);
     750           0 : }
     751             : 
     752             : // -------------------------------------
     753             : /**
     754             :  * Set an int64, via decnumber
     755             :  */
     756             : void
     757           0 : DigitList::set(int64_t source)
     758             : {
     759             :     char str[MAX_DIGITS+2];   // Leave room for sign and trailing nul.
     760           0 :     formatBase10(source, str);
     761           0 :     U_ASSERT(uprv_strlen(str) < sizeof(str));
     762             : 
     763           0 :     uprv_decNumberFromString(fDecNumber, str, &fContext);
     764           0 :     internalSetDouble(static_cast<double>(source));
     765           0 : }
     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           0 : DigitList::set(StringPiece source, UErrorCode &status, uint32_t /*fastpathBits*/) {
     778           0 :     if (U_FAILURE(status)) {
     779           0 :         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           0 :       int32_t numDigits = source.length();
     811           0 :       if (numDigits > fContext.digits) {
     812             :         // fContext.digits == fStorage.getCapacity()
     813           0 :         decNumber *t = fStorage.resize(numDigits, fStorage.getCapacity());
     814           0 :         if (t == NULL) {
     815           0 :           status = U_MEMORY_ALLOCATION_ERROR;
     816           0 :           return;
     817             :         }
     818           0 :         fDecNumber = t;
     819           0 :         fContext.digits = numDigits;
     820             :       }
     821             : 
     822           0 :       fContext.status = 0;
     823           0 :       uprv_decNumberFromString(fDecNumber, source.data(), &fContext);
     824           0 :       if ((fContext.status & DEC_Conversion_syntax) != 0) {
     825           0 :         status = U_DECIMAL_NUMBER_SYNTAX_ERROR;
     826             :       }
     827             :     }
     828           0 :     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           0 : 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           0 :     if (uprv_isInfinite(source)) {
     847           0 :         if (uprv_isNegativeInfinity(source)) {
     848           0 :             uprv_strcpy(rep,"-inf"); // Handle negative infinity
     849             :         } else {
     850           0 :             uprv_strcpy(rep,"inf");
     851             :         }
     852             :     } else {
     853           0 :         sprintf(rep, "%+1.*e", MAX_DBL_DIGITS - 1, source);
     854             :     }
     855           0 :     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           0 :     char *decimalSeparator = strchr(rep, ',');
     861           0 :     if (decimalSeparator != NULL) {
     862           0 :         *decimalSeparator = '.';
     863             :     }
     864             : 
     865             :     // Create a decNumber from the string.
     866           0 :     uprv_decNumberFromString(fDecNumber, rep, &fContext);
     867           0 :     uprv_decNumberTrim(fDecNumber);
     868           0 :     internalSetDouble(source);
     869           0 : }
     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           0 : DigitList::mult(const DigitList &other, UErrorCode &status) {
     881           0 :     if (U_FAILURE(status)) { 
     882           0 :         return; 
     883             :     } 
     884           0 :     fContext.status = 0;
     885           0 :     int32_t requiredDigits = this->digits() + other.digits();
     886           0 :     if (requiredDigits > fContext.digits) {
     887           0 :         reduce();    // Remove any trailing zeros
     888           0 :         int32_t requiredDigits = this->digits() + other.digits();
     889           0 :         ensureCapacity(requiredDigits, status);
     890             :     }
     891           0 :     uprv_decNumberMultiply(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
     892           0 :     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           0 : DigitList::div(const DigitList &other, UErrorCode &status) {
     905           0 :     if (U_FAILURE(status)) {
     906           0 :         return;
     907             :     }
     908           0 :     uprv_decNumberDivide(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
     909           0 :     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           0 : DigitList::ensureCapacity(int32_t requestedCapacity, UErrorCode &status) {
     920           0 :     if (U_FAILURE(status)) {
     921           0 :         return;
     922             :     }
     923           0 :     if (requestedCapacity <= 0) {
     924           0 :         status = U_ILLEGAL_ARGUMENT_ERROR;
     925           0 :         return;
     926             :     }
     927           0 :     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           0 :         requestedCapacity = DEC_MAX_DIGITS;
     932             :     }
     933           0 :     if (requestedCapacity > fContext.digits) {
     934           0 :         decNumber *newBuffer = fStorage.resize(requestedCapacity, fStorage.getCapacity());
     935           0 :         if (newBuffer == NULL) {
     936           0 :             status = U_MEMORY_ALLOCATION_ERROR;
     937           0 :             return;
     938             :         }
     939           0 :         fContext.digits = requestedCapacity;
     940           0 :         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           0 : DigitList::round(int32_t maximumDigits)
     953             : {
     954           0 :     reduce(); 
     955           0 :     if (maximumDigits >= fDecNumber->digits) { 
     956           0 :         return; 
     957             :     } 
     958           0 :     int32_t savedDigits  = fContext.digits;
     959           0 :     fContext.digits = maximumDigits;
     960           0 :     uprv_decNumberPlus(fDecNumber, fDecNumber, &fContext);
     961           0 :     fContext.digits = savedDigits;
     962           0 :     uprv_decNumberTrim(fDecNumber);
     963           0 :     reduce(); 
     964           0 :     internalClear();
     965             : }
     966             : 
     967             : 
     968             : void
     969           0 : DigitList::roundFixedPoint(int32_t maximumFractionDigits) {
     970           0 :     reduce();        // Remove trailing zeros. 
     971           0 :     if (fDecNumber->exponent >= -maximumFractionDigits) {
     972           0 :         return;
     973             :     }
     974             :     decNumber scale;   // Dummy decimal number, but with the desired number of
     975           0 :     uprv_decNumberZero(&scale);    //    fraction digits.
     976           0 :     scale.exponent = -maximumFractionDigits;
     977           0 :     scale.lsu[0] = 1;
     978             :     
     979           0 :     uprv_decNumberQuantize(fDecNumber, fDecNumber, &scale, &fContext);
     980           0 :     reduce(); 
     981           0 :     internalClear();
     982             : }
     983             : 
     984             : // -------------------------------------
     985             : 
     986             : void
     987           0 : DigitList::toIntegralValue() {
     988           0 :     uprv_decNumberToIntegralValue(fDecNumber, fDecNumber, &fContext);
     989           0 : }
     990             : 
     991             : 
     992             : // -------------------------------------
     993             : UBool
     994           0 : DigitList::isZero() const
     995             : {
     996           0 :     return decNumberIsZero(fDecNumber);
     997             : }
     998             : 
     999             : // -------------------------------------
    1000             : int32_t
    1001           0 : DigitList::getUpperExponent() const {
    1002           0 :     return fDecNumber->digits + fDecNumber->exponent;
    1003             : }
    1004             : 
    1005             : DigitInterval &
    1006           0 : DigitList::getSmallestInterval(DigitInterval &result) const {
    1007           0 :     result.setLeastSignificantInclusive(fDecNumber->exponent);
    1008           0 :     result.setMostSignificantExclusive(getUpperExponent());
    1009           0 :     return result;
    1010             : }
    1011             : 
    1012             : uint8_t
    1013           0 : DigitList::getDigitByExponent(int32_t exponent) const {
    1014           0 :     int32_t idx = exponent - fDecNumber->exponent;
    1015           0 :     if (idx < 0 || idx >= fDecNumber->digits) {
    1016           0 :         return 0;
    1017             :     }
    1018           0 :     return fDecNumber->lsu[idx];
    1019             : }
    1020             : 
    1021             : void
    1022           0 : DigitList::appendDigitsTo(CharString &str, UErrorCode &status) const {
    1023           0 :     str.append((const char *) fDecNumber->lsu, fDecNumber->digits, status);
    1024           0 : }
    1025             : 
    1026             : void
    1027           0 : DigitList::roundAtExponent(int32_t exponent, int32_t maxSigDigits) {
    1028           0 :     reduce();
    1029           0 :     if (maxSigDigits < fDecNumber->digits) {
    1030           0 :         int32_t minExponent = getUpperExponent() - maxSigDigits;
    1031           0 :         if (exponent < minExponent) {
    1032           0 :             exponent = minExponent;
    1033             :         }
    1034             :     }
    1035           0 :     if (exponent <= fDecNumber->exponent) {
    1036           0 :         return;
    1037             :     }
    1038           0 :     int32_t digits = getUpperExponent() - exponent;
    1039           0 :     if (digits > 0) {
    1040           0 :         round(digits);
    1041             :     } else {
    1042           0 :         roundFixedPoint(-exponent);
    1043             :     }
    1044             : }
    1045             : 
    1046             : void
    1047           0 : DigitList::quantize(const DigitList &quantity, UErrorCode &status) {
    1048           0 :     if (U_FAILURE(status)) {
    1049           0 :         return;
    1050             :     }
    1051           0 :     div(quantity, status);
    1052           0 :     roundAtExponent(0);
    1053           0 :     mult(quantity, status);
    1054           0 :     reduce();
    1055             : }
    1056             : 
    1057             : int32_t
    1058           0 : DigitList::getScientificExponent(
    1059             :         int32_t minIntDigitCount, int32_t exponentMultiplier) const {
    1060             :     // The exponent for zero is always zero.
    1061           0 :     if (isZero()) {
    1062           0 :         return 0;
    1063             :     }
    1064           0 :     int32_t intDigitCount = getUpperExponent();
    1065             :     int32_t exponent;
    1066           0 :     if (intDigitCount >= minIntDigitCount) {
    1067           0 :         int32_t maxAdjustment = intDigitCount - minIntDigitCount;
    1068           0 :         exponent = (maxAdjustment / exponentMultiplier) * exponentMultiplier;
    1069             :     } else {
    1070           0 :         int32_t minAdjustment = minIntDigitCount - intDigitCount;
    1071           0 :         exponent = ((minAdjustment + exponentMultiplier - 1) / exponentMultiplier) * -exponentMultiplier;
    1072             :     }
    1073           0 :     return exponent;
    1074             : }
    1075             : 
    1076             : int32_t
    1077           0 : DigitList::toScientific(
    1078             :         int32_t minIntDigitCount, int32_t exponentMultiplier) {
    1079             :     int32_t exponent = getScientificExponent(
    1080           0 :             minIntDigitCount, exponentMultiplier);
    1081           0 :     shiftDecimalRight(-exponent);
    1082           0 :     return exponent;
    1083             : }
    1084             : 
    1085             : void
    1086           0 : DigitList::shiftDecimalRight(int32_t n) {
    1087           0 :     fDecNumber->exponent += n;
    1088           0 :     internalClear();
    1089           0 : }
    1090             : 
    1091             : U_NAMESPACE_END
    1092             : #endif // #if !UCONFIG_NO_FORMATTING
    1093             : 
    1094             : //eof

Generated by: LCOV version 1.13