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