• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
58 static char gDecimal = 0;
59 
60 /* Only for 32 bit numbers. Ignore the negative sign. */
61 static const char LONG_MIN_REP[] = "2147483648";
62 static const char I64_MIN_REP[] = "9223372036854775808";
63 
64 
65 U_NAMESPACE_BEGIN
66 
67 // -------------------------------------
68 // default constructor
69 
DigitList()70 DigitList::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 
~DigitList()86 DigitList::~DigitList()
87 {
88 }
89 
90 // -------------------------------------
91 // copy constructor
92 
DigitList(const DigitList & other)93 DigitList::DigitList(const DigitList &other)
94 {
95     fDecNumber = fStorage.getAlias();
96     *this = other;
97 }
98 
99 
100 // -------------------------------------
101 // assignment operator
102 
103 DigitList&
operator =(const DigitList & other)104 DigitList::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 
127 UBool
operator ==(const DigitList & that) const128 DigitList::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
compare(const DigitList & other)150 int32_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.
170 void
reduce()171 DigitList::reduce() {
172     uprv_decNumberReduce(fDecNumber, fDecNumber, &fContext);
173 }
174 
175 
176 // -------------------------------------
177 //  trim - remove trailing fraction zero digits.
178 void
trim()179 DigitList::trim() {
180     uprv_decNumberTrim(fDecNumber);
181 }
182 
183 // -------------------------------------
184 // Resets the digit list; sets all the digits to zero.
185 
186 void
clear()187 DigitList::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  */
203 static int32_t
formatBase10(int64_t number,char * outputStr)204 formatBase10(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 
247 void
setRoundingMode(DecimalFormat::ERoundingMode m)248 DigitList::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 
272 void
setPositive(UBool s)273 DigitList::setPositive(UBool s) {
274     if (s) {
275         fDecNumber->bits &= ~DECNEG;
276     } else {
277         fDecNumber->bits |= DECNEG;
278     }
279     fHaveDouble = FALSE;
280 }
281 // -------------------------------------
282 
283 void
setDecimalAt(int32_t d)284 DigitList::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 
297 int32_t
getDecimalAt()298 DigitList::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 
306 void
setCount(int32_t c)307 DigitList::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 
319 int32_t
getCount() const320 DigitList::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 
330 void
setDigit(int32_t i,char v)331 DigitList::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 
340 char
getDigit(int32_t i)341 DigitList::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()
348 uint8_t
getDigitValue(int32_t i)349 DigitList::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 //
363 void
append(char digit)364 DigitList::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  */
403 double
getDouble() const404 DigitList::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  */
getLong()486 int32_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  */
getInt64()510 int64_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  */
getDecimal(CharString & str,UErrorCode & status)569 void 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  */
592 UBool
fitsIntoLong(UBool ignoreNegativeZero)593 DigitList::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  */
639 UBool
fitsIntoInt64(UBool ignoreNegativeZero)640 DigitList::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 
683 void
set(int32_t source)684 DigitList::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  */
696 void
set(int64_t source)697 DigitList::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  */
718 void
set(const StringPiece & source,UErrorCode & status)719 DigitList::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  */
751 void
set(double source)752 DigitList::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  */
776 void
mult(const DigitList & other,UErrorCode & status)777 DigitList::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  */
797 void
div(const DigitList & other,UErrorCode & status)798 DigitList::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  */
812 void
ensureCapacity(int32_t requestedCapacity,UErrorCode & status)813 DigitList::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  */
845 void
round(int32_t maximumDigits)846 DigitList::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 
857 void
roundFixedPoint(int32_t maximumFractionDigits)858 DigitList::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 
875 void
toIntegralValue()876 DigitList::toIntegralValue() {
877     uprv_decNumberToIntegralValue(fDecNumber, fDecNumber, &fContext);
878 }
879 
880 
881 // -------------------------------------
882 UBool
isZero() const883 DigitList::isZero() const
884 {
885     return decNumberIsZero(fDecNumber);
886 }
887 
888 
889 U_NAMESPACE_END
890 #endif // #if !UCONFIG_NO_FORMATTING
891 
892 //eof
893