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