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