Line data Source code
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 : # 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
64 : # if U_PLATFORM_USES_ONLY_WIN32_API || 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 :
94 0 : DigitList::DigitList()
95 : {
96 0 : uprv_decContextDefault(&fContext, DEC_INIT_BASE);
97 0 : fContext.traps = 0;
98 0 : uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN);
99 0 : fContext.digits = fStorage.getCapacity();
100 :
101 0 : fDecNumber = fStorage.getAlias();
102 0 : uprv_decNumberZero(fDecNumber);
103 :
104 0 : internalSetDouble(0.0);
105 0 : }
106 :
107 : // -------------------------------------
108 :
109 0 : DigitList::~DigitList()
110 : {
111 0 : }
112 :
113 : // -------------------------------------
114 : // copy constructor
115 :
116 0 : DigitList::DigitList(const DigitList &other)
117 : {
118 0 : fDecNumber = fStorage.getAlias();
119 0 : *this = other;
120 0 : }
121 :
122 :
123 : // -------------------------------------
124 : // assignment operator
125 :
126 : DigitList&
127 0 : DigitList::operator=(const DigitList& other)
128 : {
129 0 : if (this != &other)
130 : {
131 0 : uprv_memcpy(&fContext, &other.fContext, sizeof(decContext));
132 :
133 0 : if (other.fStorage.getCapacity() > fStorage.getCapacity()) {
134 0 : 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 0 : fContext.digits = fStorage.getCapacity();
139 0 : 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 0 : Mutex mutex;
146 :
147 0 : if(other.fHave==kDouble) {
148 0 : fUnion.fDouble = other.fUnion.fDouble;
149 : }
150 0 : fHave = other.fHave;
151 : }
152 : }
153 0 : return *this;
154 : }
155 :
156 : // -------------------------------------
157 : // operator == (does not exactly match the old DigitList function)
158 :
159 : UBool
160 0 : DigitList::operator==(const DigitList& that) const
161 : {
162 0 : if (this == &that) {
163 0 : return TRUE;
164 : }
165 : decNumber n; // Has space for only a none digit value.
166 : decContext c;
167 0 : uprv_decContextDefault(&c, DEC_INIT_BASE);
168 0 : c.digits = 1;
169 0 : c.traps = 0;
170 :
171 0 : uprv_decNumberCompare(&n, this->fDecNumber, that.fDecNumber, &c);
172 0 : UBool result = decNumberIsZero(&n);
173 0 : return result;
174 : }
175 :
176 : // -------------------------------------
177 : // comparison function. Returns
178 : // Not Comparable : -2
179 : // < : -1
180 : // == : 0
181 : // > : +1
182 0 : int32_t DigitList::compare(const DigitList &other) {
183 : decNumber result;
184 0 : int32_t savedDigits = fContext.digits;
185 0 : fContext.digits = 1;
186 0 : uprv_decNumberCompare(&result, this->fDecNumber, other.fDecNumber, &fContext);
187 0 : fContext.digits = savedDigits;
188 0 : if (decNumberIsZero(&result)) {
189 0 : return 0;
190 0 : } else if (decNumberIsSpecial(&result)) {
191 0 : return -2;
192 0 : } else if (result.bits & DECNEG) {
193 0 : return -1;
194 : } else {
195 0 : return 1;
196 : }
197 : }
198 :
199 :
200 : // -------------------------------------
201 : // Reduce - remove trailing zero digits.
202 : void
203 0 : DigitList::reduce() {
204 0 : uprv_decNumberReduce(fDecNumber, fDecNumber, &fContext);
205 0 : }
206 :
207 :
208 : // -------------------------------------
209 : // trim - remove trailing fraction zero digits.
210 : void
211 0 : DigitList::trim() {
212 0 : uprv_decNumberTrim(fDecNumber);
213 0 : }
214 :
215 : // -------------------------------------
216 : // Resets the digit list; sets all the digits to zero.
217 :
218 : void
219 0 : DigitList::clear()
220 : {
221 0 : uprv_decNumberZero(fDecNumber);
222 0 : uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN);
223 0 : internalSetDouble(0.0);
224 0 : }
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
235 0 : 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 0 : const int32_t MAX_IDX = MAX_DIGITS+2;
241 0 : int32_t destIdx = MAX_IDX;
242 0 : outputStr[--destIdx] = 0;
243 :
244 0 : int64_t n = number;
245 0 : if (number < 0) { // Negative numbers are slightly larger than a postive
246 0 : outputStr[--destIdx] = (char)(-(n % 10) + kZero);
247 0 : n /= -10;
248 : }
249 0 : do {
250 0 : outputStr[--destIdx] = (char)(n % 10 + kZero);
251 0 : n /= 10;
252 0 : } while (n > 0);
253 :
254 0 : if (number < 0) {
255 0 : outputStr[--destIdx] = '-';
256 : }
257 :
258 : // Slide the number to the start of the output str
259 0 : U_ASSERT(destIdx >= 0);
260 0 : int32_t length = MAX_IDX - destIdx;
261 0 : uprv_memmove(outputStr, outputStr+MAX_IDX-length, length);
262 :
263 0 : 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
279 0 : DigitList::setRoundingMode(DecimalFormat::ERoundingMode m) {
280 : enum rounding r;
281 :
282 0 : switch (m) {
283 0 : case DecimalFormat::kRoundCeiling: r = DEC_ROUND_CEILING; break;
284 0 : case DecimalFormat::kRoundFloor: r = DEC_ROUND_FLOOR; break;
285 0 : case DecimalFormat::kRoundDown: r = DEC_ROUND_DOWN; break;
286 0 : case DecimalFormat::kRoundUp: r = DEC_ROUND_UP; break;
287 0 : case DecimalFormat::kRoundHalfEven: r = DEC_ROUND_HALF_EVEN; break;
288 0 : case DecimalFormat::kRoundHalfDown: r = DEC_ROUND_HALF_DOWN; break;
289 0 : case DecimalFormat::kRoundHalfUp: r = DEC_ROUND_HALF_UP; break;
290 0 : case DecimalFormat::kRoundUnnecessary: r = DEC_ROUND_HALF_EVEN; break;
291 : default:
292 : // TODO: how to report the problem?
293 : // Leave existing mode unchanged.
294 0 : r = uprv_decContextGetRounding(&fContext);
295 : }
296 0 : uprv_decContextSetRounding(&fContext, r);
297 :
298 0 : }
299 :
300 :
301 : // -------------------------------------
302 :
303 : void
304 0 : DigitList::setPositive(UBool s) {
305 0 : if (s) {
306 0 : fDecNumber->bits &= ~DECNEG;
307 : } else {
308 0 : fDecNumber->bits |= DECNEG;
309 : }
310 0 : internalClear();
311 0 : }
312 : // -------------------------------------
313 :
314 : void
315 0 : DigitList::setDecimalAt(int32_t d) {
316 0 : U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0); // Not Infinity or NaN
317 0 : U_ASSERT(d-1>-999999999);
318 0 : U_ASSERT(d-1< 999999999);
319 0 : int32_t adjustedDigits = fDecNumber->digits;
320 0 : if (decNumberIsZero(fDecNumber)) {
321 : // Account for difference in how zero is represented between DigitList & decNumber.
322 0 : adjustedDigits = 0;
323 : }
324 0 : fDecNumber->exponent = d - adjustedDigits;
325 0 : internalClear();
326 0 : }
327 :
328 : int32_t
329 0 : DigitList::getDecimalAt() {
330 0 : U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0); // Not Infinity or NaN
331 0 : if (decNumberIsZero(fDecNumber) || ((fDecNumber->bits & DECSPECIAL) != 0)) {
332 0 : return fDecNumber->exponent; // Exponent should be zero for these cases.
333 : }
334 0 : return fDecNumber->exponent + fDecNumber->digits;
335 : }
336 :
337 : void
338 0 : DigitList::setCount(int32_t c) {
339 0 : U_ASSERT(c <= fContext.digits);
340 0 : 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 0 : c = 1;
344 0 : fDecNumber->lsu[0] = 0;
345 : }
346 0 : fDecNumber->digits = c;
347 0 : internalClear();
348 0 : }
349 :
350 : int32_t
351 0 : DigitList::getCount() const {
352 0 : 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 0 : return 0;
356 : } else {
357 0 : return fDecNumber->digits;
358 : }
359 : }
360 :
361 : void
362 0 : DigitList::setDigit(int32_t i, char v) {
363 0 : int32_t count = fDecNumber->digits;
364 0 : U_ASSERT(i<count);
365 0 : U_ASSERT(v>='0' && v<='9');
366 0 : v &= 0x0f;
367 0 : fDecNumber->lsu[count-i-1] = v;
368 0 : internalClear();
369 0 : }
370 :
371 : char
372 0 : DigitList::getDigit(int32_t i) {
373 0 : int32_t count = fDecNumber->digits;
374 0 : U_ASSERT(i<count);
375 0 : return fDecNumber->lsu[count-i-1] + '0';
376 : }
377 :
378 : // copied from DigitList::getDigit()
379 : uint8_t
380 0 : DigitList::getDigitValue(int32_t i) {
381 0 : int32_t count = fDecNumber->digits;
382 0 : U_ASSERT(i<count);
383 0 : 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
395 0 : DigitList::append(char digit)
396 : {
397 0 : 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 0 : 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 0 : fDecNumber->lsu[0] = digit & 0x0f;
405 0 : fDecNumber->digits = 1;
406 0 : fDecNumber->exponent--; // To match the old digit list implementation.
407 : } else {
408 0 : int32_t nDigits = fDecNumber->digits;
409 0 : if (nDigits < fContext.digits) {
410 : int i;
411 0 : for (i=nDigits; i>0; i--) {
412 0 : fDecNumber->lsu[i] = fDecNumber->lsu[i-1];
413 : }
414 0 : fDecNumber->lsu[0] = digit & 0x0f;
415 0 : 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 0 : fDecNumber->exponent--;
420 : }
421 : }
422 0 : internalClear();
423 0 : }
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
435 0 : DigitList::getDouble() const
436 : {
437 : {
438 0 : Mutex mutex;
439 0 : if (fHave == kDouble) {
440 0 : return fUnion.fDouble;
441 : }
442 : }
443 :
444 0 : double tDouble = 0.0;
445 0 : if (isZero()) {
446 0 : tDouble = 0.0;
447 0 : if (decNumberIsNegative(fDecNumber)) {
448 0 : tDouble /= -1;
449 : }
450 0 : } else if (isInfinite()) {
451 : if (std::numeric_limits<double>::has_infinity) {
452 0 : tDouble = std::numeric_limits<double>::infinity();
453 : } else {
454 : tDouble = std::numeric_limits<double>::max();
455 : }
456 0 : if (!isPositive()) {
457 0 : tDouble = -tDouble; //this was incorrectly "-fDouble" originally.
458 : }
459 : } else {
460 0 : 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 0 : if (getCount() > MAX_DBL_DIGITS + 3) {
469 0 : DigitList numToConvert(*this);
470 0 : numToConvert.reduce(); // Removes any trailing zeros, so that digit count is good.
471 0 : numToConvert.round(MAX_DBL_DIGITS+3);
472 0 : uprv_decNumberToString(numToConvert.fDecNumber, s.getAlias());
473 : // TODO: how many extra digits should be included for an accurate conversion?
474 : } else {
475 0 : uprv_decNumberToString(this->fDecNumber, s.getAlias());
476 : }
477 0 : U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18);
478 :
479 0 : char *end = NULL;
480 0 : tDouble = decimalStrToDouble(s.getAlias(), &end);
481 : }
482 : {
483 0 : Mutex mutex;
484 0 : DigitList *nonConstThis = const_cast<DigitList *>(this);
485 0 : nonConstThis->internalSetDouble(tDouble);
486 : }
487 0 : 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
503 0 : 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 0 : return TRUE;
511 : }
512 : // C Locale initialization func
513 0 : static void U_CALLCONV initCLocale(void) {
514 0 : 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 0 : }
523 : U_CDECL_END
524 :
525 : double
526 0 : DigitList::decimalStrToDouble(char *decstr, char **end) {
527 0 : umtx_initOnce(gCLocaleInitOnce, &initCLocale);
528 : #if U_USE_STRTOD_L
529 : return strtod_l(decstr, end, gCLocale);
530 : #else
531 0 : char *decimalPt = strchr(decstr, '.');
532 0 : 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 0 : sprintf(rep, "%+1.1f", 1.0);
538 0 : *decimalPt = rep[2];
539 : }
540 0 : 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 : */
550 0 : int32_t DigitList::getLong() /*const*/
551 : {
552 0 : int32_t result = 0;
553 0 : if (getUpperExponent() > 10) {
554 : // Overflow, absolute value too big.
555 0 : return result;
556 : }
557 0 : 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 0 : DigitList copy(*this);
561 0 : DigitList zero;
562 0 : uprv_decNumberQuantize(copy.fDecNumber, copy.fDecNumber, zero.fDecNumber, &fContext);
563 0 : result = uprv_decNumberToInt32(copy.fDecNumber, &fContext);
564 : } else {
565 0 : result = uprv_decNumberToInt32(fDecNumber, &fContext);
566 : }
567 0 : 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 : */
575 0 : 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 0 : if (getUpperExponent() > 19) {
583 : // Overflow, absolute value too big.
584 0 : 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 0 : int32_t numIntDigits = getUpperExponent();
597 0 : uint64_t value = 0;
598 0 : 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 0 : int32_t digitIndex = fDecNumber->digits - i - 1;
602 0 : int32_t v = (digitIndex >= 0) ? fDecNumber->lsu[digitIndex] : 0;
603 0 : value = value * (uint64_t)10 + (uint64_t)v;
604 : }
605 :
606 0 : if (decNumberIsNegative(fDecNumber)) {
607 0 : value = ~value;
608 0 : value += 1;
609 : }
610 0 : 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 0 : if (numIntDigits == 19) {
616 0 : if (( decNumberIsNegative(fDecNumber) && svalue>0) ||
617 0 : (!decNumberIsNegative(fDecNumber) && svalue<0)) {
618 0 : svalue = 0;
619 : }
620 : }
621 :
622 0 : 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 : */
631 0 : void DigitList::getDecimal(CharString &str, UErrorCode &status) {
632 0 : if (U_FAILURE(status)) {
633 0 : 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 0 : int32_t maxLength = fDecNumber->digits + 14;
639 0 : int32_t capacity = 0;
640 0 : char *buffer = str.clear().getAppendBuffer(maxLength, 0, capacity, status);
641 0 : if (U_FAILURE(status)) {
642 0 : return; // Memory allocation error on growing the string.
643 : }
644 0 : U_ASSERT(capacity >= maxLength);
645 0 : uprv_decNumberToString(this->fDecNumber, buffer);
646 0 : U_ASSERT((int32_t)uprv_strlen(buffer) <= maxLength);
647 0 : 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
655 0 : DigitList::fitsIntoLong(UBool ignoreNegativeZero) /*const*/
656 : {
657 0 : if (decNumberIsSpecial(this->fDecNumber)) {
658 : // NaN or Infinity. Does not fit in int32.
659 0 : return FALSE;
660 : }
661 0 : uprv_decNumberTrim(this->fDecNumber);
662 0 : if (fDecNumber->exponent < 0) {
663 : // Number contains fraction digits.
664 0 : return FALSE;
665 : }
666 0 : if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero &&
667 0 : (fDecNumber->bits & DECNEG) != 0) {
668 : // Negative Zero, not ingored. Cannot represent as a long.
669 0 : return FALSE;
670 : }
671 0 : 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 0 : 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 0 : UErrorCode status = U_ZERO_ERROR;
681 0 : DigitList min32; min32.set("-2147483648", status);
682 0 : if (this->compare(min32) < 0) {
683 0 : return FALSE;
684 : }
685 0 : DigitList max32; max32.set("2147483647", status);
686 0 : if (this->compare(max32) > 0) {
687 0 : return FALSE;
688 : }
689 0 : if (U_FAILURE(status)) {
690 0 : return FALSE;
691 : }
692 0 : 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
702 0 : DigitList::fitsIntoInt64(UBool ignoreNegativeZero) /*const*/
703 : {
704 0 : if (decNumberIsSpecial(this->fDecNumber)) {
705 : // NaN or Infinity. Does not fit in int32.
706 0 : return FALSE;
707 : }
708 0 : uprv_decNumberTrim(this->fDecNumber);
709 0 : if (fDecNumber->exponent < 0) {
710 : // Number contains fraction digits.
711 0 : return FALSE;
712 : }
713 0 : if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero &&
714 0 : (fDecNumber->bits & DECNEG) != 0) {
715 : // Negative Zero, not ingored. Cannot represent as a long.
716 0 : return FALSE;
717 : }
718 0 : 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 0 : 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 0 : UErrorCode status = U_ZERO_ERROR;
728 0 : DigitList min64; min64.set("-9223372036854775808", status);
729 0 : if (this->compare(min64) < 0) {
730 0 : return FALSE;
731 : }
732 0 : DigitList max64; max64.set("9223372036854775807", status);
733 0 : if (this->compare(max64) > 0) {
734 0 : return FALSE;
735 : }
736 0 : if (U_FAILURE(status)) {
737 0 : return FALSE;
738 : }
739 0 : return true;
740 : }
741 :
742 :
743 : // -------------------------------------
744 :
745 : void
746 0 : DigitList::set(int32_t source)
747 : {
748 0 : set((int64_t)source);
749 0 : internalSetDouble(source);
750 0 : }
751 :
752 : // -------------------------------------
753 : /**
754 : * Set an int64, via decnumber
755 : */
756 : void
757 0 : DigitList::set(int64_t source)
758 : {
759 : char str[MAX_DIGITS+2]; // Leave room for sign and trailing nul.
760 0 : formatBase10(source, str);
761 0 : U_ASSERT(uprv_strlen(str) < sizeof(str));
762 :
763 0 : uprv_decNumberFromString(fDecNumber, str, &fContext);
764 0 : internalSetDouble(static_cast<double>(source));
765 0 : }
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
777 0 : DigitList::set(StringPiece source, UErrorCode &status, uint32_t /*fastpathBits*/) {
778 0 : if (U_FAILURE(status)) {
779 0 : 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 0 : int32_t numDigits = source.length();
811 0 : if (numDigits > fContext.digits) {
812 : // fContext.digits == fStorage.getCapacity()
813 0 : decNumber *t = fStorage.resize(numDigits, fStorage.getCapacity());
814 0 : if (t == NULL) {
815 0 : status = U_MEMORY_ALLOCATION_ERROR;
816 0 : return;
817 : }
818 0 : fDecNumber = t;
819 0 : fContext.digits = numDigits;
820 : }
821 :
822 0 : fContext.status = 0;
823 0 : uprv_decNumberFromString(fDecNumber, source.data(), &fContext);
824 0 : if ((fContext.status & DEC_Conversion_syntax) != 0) {
825 0 : status = U_DECIMAL_NUMBER_SYNTAX_ERROR;
826 : }
827 : }
828 0 : 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
837 0 : 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 0 : if (uprv_isInfinite(source)) {
847 0 : if (uprv_isNegativeInfinity(source)) {
848 0 : uprv_strcpy(rep,"-inf"); // Handle negative infinity
849 : } else {
850 0 : uprv_strcpy(rep,"inf");
851 : }
852 : } else {
853 0 : sprintf(rep, "%+1.*e", MAX_DBL_DIGITS - 1, source);
854 : }
855 0 : 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 0 : char *decimalSeparator = strchr(rep, ',');
861 0 : if (decimalSeparator != NULL) {
862 0 : *decimalSeparator = '.';
863 : }
864 :
865 : // Create a decNumber from the string.
866 0 : uprv_decNumberFromString(fDecNumber, rep, &fContext);
867 0 : uprv_decNumberTrim(fDecNumber);
868 0 : internalSetDouble(source);
869 0 : }
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
880 0 : DigitList::mult(const DigitList &other, UErrorCode &status) {
881 0 : if (U_FAILURE(status)) {
882 0 : return;
883 : }
884 0 : fContext.status = 0;
885 0 : int32_t requiredDigits = this->digits() + other.digits();
886 0 : if (requiredDigits > fContext.digits) {
887 0 : reduce(); // Remove any trailing zeros
888 0 : int32_t requiredDigits = this->digits() + other.digits();
889 0 : ensureCapacity(requiredDigits, status);
890 : }
891 0 : uprv_decNumberMultiply(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
892 0 : 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
904 0 : DigitList::div(const DigitList &other, UErrorCode &status) {
905 0 : if (U_FAILURE(status)) {
906 0 : return;
907 : }
908 0 : uprv_decNumberDivide(fDecNumber, fDecNumber, other.fDecNumber, &fContext);
909 0 : 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
919 0 : DigitList::ensureCapacity(int32_t requestedCapacity, UErrorCode &status) {
920 0 : if (U_FAILURE(status)) {
921 0 : return;
922 : }
923 0 : if (requestedCapacity <= 0) {
924 0 : status = U_ILLEGAL_ARGUMENT_ERROR;
925 0 : return;
926 : }
927 0 : 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 0 : requestedCapacity = DEC_MAX_DIGITS;
932 : }
933 0 : if (requestedCapacity > fContext.digits) {
934 0 : decNumber *newBuffer = fStorage.resize(requestedCapacity, fStorage.getCapacity());
935 0 : if (newBuffer == NULL) {
936 0 : status = U_MEMORY_ALLOCATION_ERROR;
937 0 : return;
938 : }
939 0 : fContext.digits = requestedCapacity;
940 0 : 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
952 0 : DigitList::round(int32_t maximumDigits)
953 : {
954 0 : reduce();
955 0 : if (maximumDigits >= fDecNumber->digits) {
956 0 : return;
957 : }
958 0 : int32_t savedDigits = fContext.digits;
959 0 : fContext.digits = maximumDigits;
960 0 : uprv_decNumberPlus(fDecNumber, fDecNumber, &fContext);
961 0 : fContext.digits = savedDigits;
962 0 : uprv_decNumberTrim(fDecNumber);
963 0 : reduce();
964 0 : internalClear();
965 : }
966 :
967 :
968 : void
969 0 : DigitList::roundFixedPoint(int32_t maximumFractionDigits) {
970 0 : reduce(); // Remove trailing zeros.
971 0 : if (fDecNumber->exponent >= -maximumFractionDigits) {
972 0 : return;
973 : }
974 : decNumber scale; // Dummy decimal number, but with the desired number of
975 0 : uprv_decNumberZero(&scale); // fraction digits.
976 0 : scale.exponent = -maximumFractionDigits;
977 0 : scale.lsu[0] = 1;
978 :
979 0 : uprv_decNumberQuantize(fDecNumber, fDecNumber, &scale, &fContext);
980 0 : reduce();
981 0 : internalClear();
982 : }
983 :
984 : // -------------------------------------
985 :
986 : void
987 0 : DigitList::toIntegralValue() {
988 0 : uprv_decNumberToIntegralValue(fDecNumber, fDecNumber, &fContext);
989 0 : }
990 :
991 :
992 : // -------------------------------------
993 : UBool
994 0 : DigitList::isZero() const
995 : {
996 0 : return decNumberIsZero(fDecNumber);
997 : }
998 :
999 : // -------------------------------------
1000 : int32_t
1001 0 : DigitList::getUpperExponent() const {
1002 0 : return fDecNumber->digits + fDecNumber->exponent;
1003 : }
1004 :
1005 : DigitInterval &
1006 0 : DigitList::getSmallestInterval(DigitInterval &result) const {
1007 0 : result.setLeastSignificantInclusive(fDecNumber->exponent);
1008 0 : result.setMostSignificantExclusive(getUpperExponent());
1009 0 : return result;
1010 : }
1011 :
1012 : uint8_t
1013 0 : DigitList::getDigitByExponent(int32_t exponent) const {
1014 0 : int32_t idx = exponent - fDecNumber->exponent;
1015 0 : if (idx < 0 || idx >= fDecNumber->digits) {
1016 0 : return 0;
1017 : }
1018 0 : return fDecNumber->lsu[idx];
1019 : }
1020 :
1021 : void
1022 0 : DigitList::appendDigitsTo(CharString &str, UErrorCode &status) const {
1023 0 : str.append((const char *) fDecNumber->lsu, fDecNumber->digits, status);
1024 0 : }
1025 :
1026 : void
1027 0 : DigitList::roundAtExponent(int32_t exponent, int32_t maxSigDigits) {
1028 0 : reduce();
1029 0 : if (maxSigDigits < fDecNumber->digits) {
1030 0 : int32_t minExponent = getUpperExponent() - maxSigDigits;
1031 0 : if (exponent < minExponent) {
1032 0 : exponent = minExponent;
1033 : }
1034 : }
1035 0 : if (exponent <= fDecNumber->exponent) {
1036 0 : return;
1037 : }
1038 0 : int32_t digits = getUpperExponent() - exponent;
1039 0 : if (digits > 0) {
1040 0 : round(digits);
1041 : } else {
1042 0 : roundFixedPoint(-exponent);
1043 : }
1044 : }
1045 :
1046 : void
1047 0 : DigitList::quantize(const DigitList &quantity, UErrorCode &status) {
1048 0 : if (U_FAILURE(status)) {
1049 0 : return;
1050 : }
1051 0 : div(quantity, status);
1052 0 : roundAtExponent(0);
1053 0 : mult(quantity, status);
1054 0 : reduce();
1055 : }
1056 :
1057 : int32_t
1058 0 : DigitList::getScientificExponent(
1059 : int32_t minIntDigitCount, int32_t exponentMultiplier) const {
1060 : // The exponent for zero is always zero.
1061 0 : if (isZero()) {
1062 0 : return 0;
1063 : }
1064 0 : int32_t intDigitCount = getUpperExponent();
1065 : int32_t exponent;
1066 0 : if (intDigitCount >= minIntDigitCount) {
1067 0 : int32_t maxAdjustment = intDigitCount - minIntDigitCount;
1068 0 : exponent = (maxAdjustment / exponentMultiplier) * exponentMultiplier;
1069 : } else {
1070 0 : int32_t minAdjustment = minIntDigitCount - intDigitCount;
1071 0 : exponent = ((minAdjustment + exponentMultiplier - 1) / exponentMultiplier) * -exponentMultiplier;
1072 : }
1073 0 : return exponent;
1074 : }
1075 :
1076 : int32_t
1077 0 : DigitList::toScientific(
1078 : int32_t minIntDigitCount, int32_t exponentMultiplier) {
1079 : int32_t exponent = getScientificExponent(
1080 0 : minIntDigitCount, exponentMultiplier);
1081 0 : shiftDecimalRight(-exponent);
1082 0 : return exponent;
1083 : }
1084 :
1085 : void
1086 0 : DigitList::shiftDecimalRight(int32_t n) {
1087 0 : fDecNumber->exponent += n;
1088 0 : internalClear();
1089 0 : }
1090 :
1091 : U_NAMESPACE_END
1092 : #endif // #if !UCONFIG_NO_FORMATTING
1093 :
1094 : //eof
|