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