diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /intl/icu/source/i18n/visibledigits.cpp | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'intl/icu/source/i18n/visibledigits.cpp')
-rw-r--r-- | intl/icu/source/i18n/visibledigits.cpp | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/intl/icu/source/i18n/visibledigits.cpp b/intl/icu/source/i18n/visibledigits.cpp new file mode 100644 index 000000000..1fea3504d --- /dev/null +++ b/intl/icu/source/i18n/visibledigits.cpp @@ -0,0 +1,186 @@ +// Copyright (C) 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* + * Copyright (C) 2016, International Business Machines + * Corporation and others. All Rights Reserved. + * + * file name: visibledigits.cpp + */ + +#include <math.h> + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "cstring.h" +#include "decNumber.h" +#include "digitlst.h" +#include "uassert.h" +#include "visibledigits.h" + +static const int32_t kNegative = 1; +static const int32_t kInfinite = 2; +static const int32_t kNaN = 4; + +U_NAMESPACE_BEGIN + +void VisibleDigits::setNegative() { + fFlags |= kNegative; +} + +void VisibleDigits::setNaN() { + fFlags |= kNaN; +} + +void VisibleDigits::setInfinite() { + fFlags |= kInfinite; +} + +void VisibleDigits::clear() { + fInterval.clear(); + fDigits.clear(); + fExponent = 0; + fFlags = 0; + fAbsIntValue = 0LL; + fAbsIntValueSet = FALSE; + fAbsDoubleValue = 0.0; + fAbsDoubleValueSet = FALSE; +} + +UBool VisibleDigits::isNegative() const { + return (fFlags & kNegative); +} + +UBool VisibleDigits::isNaN() const { + return (fFlags & kNaN); +} + +UBool VisibleDigits::isInfinite() const { + return (fFlags & kInfinite); +} + +int32_t VisibleDigits::getDigitByExponent(int32_t digitPos) const { + if (digitPos < fExponent || digitPos >= fExponent + fDigits.length()) { + return 0; + } + const char *ptr = fDigits.data(); + return ptr[digitPos - fExponent]; +} + +UBool VisibleDigits::isOverMaxDigits() const { + return (fExponent + fDigits.length() > fInterval.getMostSignificantExclusive()); +} + +UBool VisibleDigits::isNaNOrInfinity() const { + return (fFlags & (kInfinite | kNaN)) != 0; +} + +double VisibleDigits::computeAbsDoubleValue() const { + // Take care of NaN and infinity + if (isNaN()) { + return uprv_getNaN(); + } + if (isInfinite()) { + return uprv_getInfinity(); + } + + // stack allocate a decNumber to hold MAX_DBL_DIGITS+3 significant digits + struct { + decNumber decNum; + char digits[MAX_DBL_DIGITS+3]; + } decNumberWithStorage; + decNumber *numberPtr = &decNumberWithStorage.decNum; + + int32_t mostSig = fInterval.getMostSignificantExclusive(); + int32_t mostSigNonZero = fExponent + fDigits.length(); + int32_t end = mostSig > mostSigNonZero ? mostSigNonZero : mostSig; + int32_t leastSig = fInterval.getLeastSignificantInclusive(); + int32_t start = leastSig > fExponent ? leastSig : fExponent; + if (end <= start) { + return 0.0; + } + if (start < end - (MAX_DBL_DIGITS+3)) { + start = end - (MAX_DBL_DIGITS+3); + } + uint8_t *pos = numberPtr->lsu; + const char *src = &(fDigits.data()[start - fExponent]); + for (int32_t i = start; i < end; ++i) { + *pos++ = (uint8_t) (*src++); + } + numberPtr->exponent = start; + numberPtr->bits = 0; + numberPtr->digits = end - start; + char str[MAX_DBL_DIGITS+18]; + uprv_decNumberToString(numberPtr, str); + U_ASSERT(uprv_strlen(str) < MAX_DBL_DIGITS+18); + char *unused = NULL; + return DigitList::decimalStrToDouble(str, &unused); +} + +void VisibleDigits::getFixedDecimal( + double &source, int64_t &intValue, int64_t &f, int64_t &t, int32_t &v, UBool &hasIntValue) const { + source = 0.0; + intValue = 0; + f = 0; + t = 0; + v = 0; + hasIntValue = FALSE; + if (isNaNOrInfinity()) { + return; + } + + // source + if (fAbsDoubleValueSet) { + source = fAbsDoubleValue; + } else { + source = computeAbsDoubleValue(); + } + + // visible decimal digits + v = fInterval.getFracDigitCount(); + + // intValue + + // If we initialized from an int64 just use that instead of + // calculating + if (fAbsIntValueSet) { + intValue = fAbsIntValue; + } else { + int32_t startPos = fInterval.getMostSignificantExclusive(); + if (startPos > 18) { + startPos = 18; + } + // process the integer digits + for (int32_t i = startPos - 1; i >= 0; --i) { + intValue = intValue * 10LL + getDigitByExponent(i); + } + if (intValue == 0LL && startPos > 0) { + intValue = 100000000000000000LL; + } + } + + // f (decimal digits) + // skip over any leading 0's in fraction digits. + int32_t idx = -1; + for (; idx >= -v && getDigitByExponent(idx) == 0; --idx) + ; + + // Only process up to first 18 non zero fraction digits for decimalDigits + // since that is all we can fit into an int64. + for (int32_t i = idx; i >= -v && i > idx - 18; --i) { + f = f * 10LL + getDigitByExponent(i); + } + + // If we have no decimal digits, we don't have an integer value + hasIntValue = (f == 0LL); + + // t (decimal digits without trailing zeros) + t = f; + while (t > 0 && t % 10LL == 0) { + t /= 10; + } +} + +U_NAMESPACE_END +#endif /* #if !UCONFIG_NO_FORMATTING */ |