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