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