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