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