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