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