diff options
Diffstat (limited to 'deps/icu-small/source/i18n/nfsubs.cpp')
-rw-r--r-- | deps/icu-small/source/i18n/nfsubs.cpp | 87 |
1 files changed, 48 insertions, 39 deletions
diff --git a/deps/icu-small/source/i18n/nfsubs.cpp b/deps/icu-small/source/i18n/nfsubs.cpp index 58039c8bac..6e7eabe350 100644 --- a/deps/icu-small/source/i18n/nfsubs.cpp +++ b/deps/icu-small/source/i18n/nfsubs.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2016 and later: Unicode, Inc. and others. +// © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html /* ****************************************************************************** @@ -6,7 +6,7 @@ * Corporation and others. All Rights Reserved. ****************************************************************************** * file name: nfsubs.cpp -* encoding: US-ASCII +* encoding: UTF-8 * tab size: 8 (not used) * indentation:4 * @@ -20,6 +20,7 @@ #include "nfsubs.h" #include "digitlst.h" +#include "fmtableimp.h" #if U_HAVE_RBNF @@ -68,27 +69,24 @@ public: SameValueSubstitution::~SameValueSubstitution() {} class MultiplierSubstitution : public NFSubstitution { - double divisor; - int64_t ldivisor; + int64_t divisor; public: MultiplierSubstitution(int32_t _pos, - double _divisor, + const NFRule *rule, const NFRuleSet* _ruleSet, const UnicodeString& description, UErrorCode& status) - : NFSubstitution(_pos, _ruleSet, description, status), divisor(_divisor) + : NFSubstitution(_pos, _ruleSet, description, status), divisor(rule->getDivisor()) { - ldivisor = util64_fromDouble(divisor); if (divisor == 0) { status = U_PARSE_ERROR; } } virtual ~MultiplierSubstitution(); - virtual void setDivisor(int32_t radix, int32_t exponent, UErrorCode& status) { - divisor = uprv_pow(radix, exponent); - ldivisor = util64_fromDouble(divisor); + virtual void setDivisor(int32_t radix, int16_t exponent, UErrorCode& status) { + divisor = util64_pow(radix, exponent); if(divisor == 0) { status = U_PARSE_ERROR; @@ -98,14 +96,14 @@ public: virtual UBool operator==(const NFSubstitution& rhs) const; virtual int64_t transformNumber(int64_t number) const { - return number / ldivisor; + return number / divisor; } virtual double transformNumber(double number) const { if (getRuleSet()) { return uprv_floor(number / divisor); } else { - return number/divisor; + return number / divisor; } } @@ -125,21 +123,19 @@ public: MultiplierSubstitution::~MultiplierSubstitution() {} class ModulusSubstitution : public NFSubstitution { - double divisor; - int64_t ldivisor; + int64_t divisor; const NFRule* ruleToUse; public: ModulusSubstitution(int32_t pos, - double _divisor, + const NFRule* rule, const NFRule* rulePredecessor, const NFRuleSet* ruleSet, const UnicodeString& description, UErrorCode& status); virtual ~ModulusSubstitution(); - virtual void setDivisor(int32_t radix, int32_t exponent, UErrorCode& status) { - divisor = uprv_pow(radix, exponent); - ldivisor = util64_fromDouble(divisor); + virtual void setDivisor(int32_t radix, int16_t exponent, UErrorCode& status) { + divisor = util64_pow(radix, exponent); if (divisor == 0) { status = U_PARSE_ERROR; @@ -151,7 +147,7 @@ public: virtual void doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t pos, int32_t recursionCount, UErrorCode& status) const; virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos, int32_t recursionCount, UErrorCode& status) const; - virtual int64_t transformNumber(int64_t number) const { return number % ldivisor; } + virtual int64_t transformNumber(int64_t number) const { return number % divisor; } virtual double transformNumber(double number) const { return uprv_fmod(number, divisor); } virtual UBool doParse(const UnicodeString& text, @@ -353,7 +349,7 @@ NFSubstitution::makeSubstitution(int32_t pos, // otherwise, return a MultiplierSubstitution else { - return new MultiplierSubstitution(pos, rule->getDivisor(), ruleSet, + return new MultiplierSubstitution(pos, rule, ruleSet, description, status); } @@ -383,7 +379,7 @@ NFSubstitution::makeSubstitution(int32_t pos, // otherwise, return a ModulusSubstitution else { - return new ModulusSubstitution(pos, rule->getDivisor(), predecessor, + return new ModulusSubstitution(pos, rule, predecessor, ruleSet, description, status); } @@ -491,7 +487,7 @@ NFSubstitution::~NFSubstitution() * @param exponent The exponent of the divisor */ void -NFSubstitution::setDivisor(int32_t /*radix*/, int32_t /*exponent*/, UErrorCode& /*status*/) { +NFSubstitution::setDivisor(int32_t /*radix*/, int16_t /*exponent*/, UErrorCode& /*status*/) { // a no-op for all substitutions except multiplier and modulus substitutions } @@ -572,23 +568,38 @@ void NFSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t _pos, int32_t recursionCount, UErrorCode& status) const { if (ruleSet != NULL) { - // perform a transformation on the number that is dependent + // Perform a transformation on the number that is dependent // on the type of substitution this is, then just call its // rule set's format() method to format the result ruleSet->format(transformNumber(number), toInsertInto, _pos + this->pos, recursionCount, status); } else if (numberFormat != NULL) { - // or perform the transformation on the number (preserving - // the result's fractional part if the formatter it set - // to show it), then use that formatter's format() method - // to format the result - double numberToFormat = transformNumber((double)number); - if (numberFormat->getMaximumFractionDigits() == 0) { - numberToFormat = uprv_floor(numberToFormat); - } + if (number <= MAX_INT64_IN_DOUBLE) { + // or perform the transformation on the number (preserving + // the result's fractional part if the formatter it set + // to show it), then use that formatter's format() method + // to format the result + double numberToFormat = transformNumber((double)number); + if (numberFormat->getMaximumFractionDigits() == 0) { + numberToFormat = uprv_floor(numberToFormat); + } - UnicodeString temp; - numberFormat->format(numberToFormat, temp, status); - toInsertInto.insert(_pos + this->pos, temp); + UnicodeString temp; + numberFormat->format(numberToFormat, temp, status); + toInsertInto.insert(_pos + this->pos, temp); + } + else { + // We have gone beyond double precision. Something has to give. + // We're favoring accuracy of the large number over potential rules + // that round like a CompactDecimalFormat, which is not a common use case. + // + // Perform a transformation on the number that is dependent + // on the type of substitution this is, then just call its + // rule set's format() method to format the result + int64_t numberToFormat = transformNumber(number); + UnicodeString temp; + numberFormat->format(numberToFormat, temp, status); + toInsertInto.insert(_pos + this->pos, temp); + } } } @@ -809,22 +820,20 @@ UBool MultiplierSubstitution::operator==(const NFSubstitution& rhs) const * regular rule. */ ModulusSubstitution::ModulusSubstitution(int32_t _pos, - double _divisor, + const NFRule* rule, const NFRule* predecessor, const NFRuleSet* _ruleSet, const UnicodeString& description, UErrorCode& status) : NFSubstitution(_pos, _ruleSet, description, status) - , divisor(_divisor) + , divisor(rule->getDivisor()) , ruleToUse(NULL) { - ldivisor = util64_fromDouble(_divisor); - // the owning rule's divisor controls the behavior of this // substitution: rather than keeping a backpointer to the rule, // we keep a copy of the divisor - if (ldivisor == 0) { + if (divisor == 0) { status = U_PARSE_ERROR; } |