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