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