]> granicus.if.org Git - icu/commitdiff
ICU-10273 Plural Rules Fixed Decimal, improve handling of NaN and Infinity
authorAndy Heninger <andy.heninger@gmail.com>
Fri, 6 Sep 2013 20:02:42 +0000 (20:02 +0000)
committerAndy Heninger <andy.heninger@gmail.com>
Fri, 6 Sep 2013 20:02:42 +0000 (20:02 +0000)
X-SVN-Rev: 34225

icu4c/source/i18n/decimfmt.cpp
icu4c/source/i18n/plurrule.cpp
icu4c/source/i18n/plurrule_impl.h
icu4c/source/test/intltest/dcfmapts.cpp

index cfaa7907bc193c800cc90dc1b96ae85cbde8d773..f18284bed644e50c464c56d3ad51a46e4d0456b4 100644 (file)
@@ -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 &&
index a86ee2bf4d8a137c45ccebb12bb414a1e4084261..e8f381a2c822ca4ec7aa35bcb2fad0c6628143ab 100644 (file)
@@ -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);
index c9e7f4050ca2b2563e8b73312647de53934d8375..cfd5bc0a876a17f6c6f24ce1026c8218dbacb49f 100644 (file)
@@ -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);
index f4df4f4d4afc6eb611b7085844e1a937dc8bc4ce..d9c21c0704a6673c859f958883474d646ea7f55c 100644 (file)
@@ -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 */