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