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