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 61static const uint8_t DIGIT_HAVE_NONE=0; 62static const uint8_t DIGIT_HAVE_DOUBLE=1; 63static const uint8_t DIGIT_HAVE_INT64=2; 64 65U_NAMESPACE_BEGIN 66 67// ------------------------------------- 68// default constructor 69 70DigitList::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 85DigitList::~DigitList() 86{ 87} 88 89// ------------------------------------- 90// copy constructor 91 92DigitList::DigitList(const DigitList &other) 93{ 94 fDecNumber = fStorage.getAlias(); 95 *this = other; 96} 97 98 99// ------------------------------------- 100// assignment operator 101 102DigitList& 103DigitList::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 137UBool 138DigitList::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 160int32_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. 180void 181DigitList::reduce() { 182 uprv_decNumberReduce(fDecNumber, fDecNumber, &fContext); 183} 184 185 186// ------------------------------------- 187// trim - remove trailing fraction zero digits. 188void 189DigitList::trim() { 190 uprv_decNumberTrim(fDecNumber); 191} 192 193// ------------------------------------- 194// Resets the digit list; sets all the digits to zero. 195 196void 197DigitList::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 */ 212static int32_t 213formatBase10(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 256void 257DigitList::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 281void 282DigitList::setPositive(UBool s) { 283 if (s) { 284 fDecNumber->bits &= ~DECNEG; 285 } else { 286 fDecNumber->bits |= DECNEG; 287 } 288 internalClear(); 289} 290// ------------------------------------- 291 292void 293DigitList::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 306int32_t 307DigitList::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 315void 316DigitList::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 328int32_t 329DigitList::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 339void 340DigitList::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 349char 350DigitList::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() 357uint8_t 358DigitList::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// 372void 373DigitList::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 */ 412double 413DigitList::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 */ 496int32_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 */ 521int64_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 */ 578void 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 */ 601UBool 602DigitList::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 */ 648UBool 649DigitList::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 692void 693DigitList::set(int32_t source) 694{ 695 set((int64_t)source); 696 internalSetDouble(source); 697} 698 699// ------------------------------------- 700/** 701 * Set an int64, via decnumber 702 */ 703void 704DigitList::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 */ 717void 718DigitList::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 */ 734void 735DigitList::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 */ 794void 795DigitList::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 */ 837void 838DigitList::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 */ 858void 859DigitList::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 */ 873void 874DigitList::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 */ 906void 907DigitList::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 918void 919DigitList::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 936void 937DigitList::toIntegralValue() { 938 uprv_decNumberToIntegralValue(fDecNumber, fDecNumber, &fContext); 939} 940 941 942// ------------------------------------- 943UBool 944DigitList::isZero() const 945{ 946 return decNumberIsZero(fDecNumber); 947} 948 949U_NAMESPACE_END 950#endif // #if !UCONFIG_NO_FORMATTING 951 952//eof 953