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