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