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