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