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