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