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