From 4d9fad13efa3afaf4a912ab60a6535c36daee4bf Mon Sep 17 00:00:00 2001 From: Andy Heninger Date: Fri, 6 Sep 2013 20:02:42 +0000 Subject: [PATCH] ICU-10273 Plural Rules Fixed Decimal, improve handling of NaN and Infinity X-SVN-Rev: 34225 --- icu4c/source/i18n/decimfmt.cpp | 11 +++++++++++ icu4c/source/i18n/plurrule.cpp | 20 ++++++++++++-------- icu4c/source/i18n/plurrule_impl.h | 14 ++++++++++---- icu4c/source/test/intltest/dcfmapts.cpp | 12 +++++++++--- 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/icu4c/source/i18n/decimfmt.cpp b/icu4c/source/i18n/decimfmt.cpp index cfaa7907bc1..f18284bed64 100644 --- a/icu4c/source/i18n/decimfmt.cpp +++ b/icu4c/source/i18n/decimfmt.cpp @@ -1024,6 +1024,17 @@ DecimalFormat::clone() const FixedDecimal DecimalFormat::getFixedDecimal(double number, UErrorCode &status) const { FixedDecimal result; + + if (U_FAILURE(status)) { + return result; + } + + if (uprv_isNaN(number) || uprv_isPositiveInfinity(fabs(number))) { + // For NaN and Infinity the state of the formatter is ignored. + result.init(number); + return result; + } + int32_t minFractionDigits = getMinimumFractionDigits(); if (fMultiplier == NULL && fScale == 0 && fRoundingIncrement == 0 && areSignificantDigitsUsed() == FALSE && diff --git a/icu4c/source/i18n/plurrule.cpp b/icu4c/source/i18n/plurrule.cpp index a86ee2bf4d8..e8f381a2c82 100644 --- a/icu4c/source/i18n/plurrule.cpp +++ b/icu4c/source/i18n/plurrule.cpp @@ -817,10 +817,12 @@ RuleChain::~RuleChain() { UnicodeString RuleChain::select(const FixedDecimal &number) const { - for (const RuleChain *rules = this; rules != NULL; rules = rules->fNext) { - if (rules->ruleHeader->isFulfilled(number)) { - return rules->fKeyword; - } + if (!number.isNanOrInfinity) { + for (const RuleChain *rules = this; rules != NULL; rules = rules->fNext) { + if (rules->ruleHeader->isFulfilled(number)) { + return rules->fKeyword; + } + } } return UnicodeString(TRUE, PLURAL_KEYWORD_OTHER, 5); } @@ -1382,6 +1384,11 @@ void FixedDecimal::init(double n) { void FixedDecimal::init(double n, int32_t v, int64_t f) { isNegative = n < 0; source = fabs(n); + isNanOrInfinity = uprv_isNaN(source) || uprv_isPositiveInfinity(source); + if (isNanOrInfinity) { + v = 0; + f = 0; + } visibleDecimalDigitCount = v; decimalDigits = f; intValue = (int64_t)source; @@ -1395,9 +1402,6 @@ void FixedDecimal::init(double n, int32_t v, int64_t f) { } decimalDigitsWithoutTrailingZeros = fdwtz; } - if (uprv_isNaN(n)) { - isNanOrInfinity = TRUE; - } } @@ -1405,7 +1409,7 @@ void FixedDecimal::init(double n, int32_t v, int64_t f) { // Note: Do not multiply by 10 each time through loop, rounding cruft can build // up that makes the check for an integer result fail. // A single multiply of the original number works more reliably. -static int p10[] = {1, 10, 100, 1000, 10000}; +static int32_t p10[] = {1, 10, 100, 1000, 10000}; UBool FixedDecimal::quickInit(double n) { UBool success = FALSE; n = fabs(n); diff --git a/icu4c/source/i18n/plurrule_impl.h b/icu4c/source/i18n/plurrule_impl.h index c9e7f4050ca..cfd5bc0a876 100644 --- a/icu4c/source/i18n/plurrule_impl.h +++ b/icu4c/source/i18n/plurrule_impl.h @@ -170,13 +170,19 @@ private: }; +/** + * class FixedDecimal serves to communicate the properties + * of a formatted number from a decimal formatter to PluralRules::select() + * + * see DecimalFormat::getFixedDecimal() + * @internal + */ class U_I18N_API FixedDecimal: public UMemory { public: /** - * @param n the number - * @param v The number of visible fraction digits - * @param f The fraction digits. - * + * @param n the number, e.g. 12.345 + * @param v The number of visible fraction digits, e.g. 3 + * @param f The fraction digits, e.g. 345 */ FixedDecimal(double n, int32_t v, int64_t f); FixedDecimal(double n, int32_t); diff --git a/icu4c/source/test/intltest/dcfmapts.cpp b/icu4c/source/test/intltest/dcfmapts.cpp index f4df4f4d4af..d9c21c0704a 100644 --- a/icu4c/source/test/intltest/dcfmapts.cpp +++ b/icu4c/source/test/intltest/dcfmapts.cpp @@ -16,6 +16,7 @@ #include "unicode/localpointer.h" #include "unicode/parseerr.h" +#include "putilimp.h" #include "plurrule_impl.h" #define LENGTHOF(array) ((int32_t)(sizeof(array)/sizeof((array)[0]))) @@ -657,9 +658,14 @@ void IntlTestDecimalFormatAPI::TestFixedDecimal() { ASSERT_EQUAL(FALSE, fd.hasIntegerValue); ASSERT_EQUAL(FALSE, fd.isNegative); - - - + fd = df->getFixedDecimal(uprv_getInfinity(), status); + ASSERT_SUCCESS(status); + ASSERT_EQUAL(TRUE, fd.isNanOrInfinity); + fd = df->getFixedDecimal(0.0, status); + ASSERT_EQUAL(FALSE, fd.isNanOrInfinity); + fd = df->getFixedDecimal(uprv_getNaN(), status); + ASSERT_EQUAL(TRUE, fd.isNanOrInfinity); + ASSERT_SUCCESS(status); } #endif /* #if !UCONFIG_NO_FORMATTING */ -- 2.40.0