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