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