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