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