[Libreoffice-commits] core.git: 2 commits - sal/qa sal/rtl

Eike Rathke erack at redhat.com
Wed Jan 13 05:48:41 PST 2016


 sal/qa/rtl/math/test-rtl-math.cxx |   41 +++++++++++++++++++++++
 sal/rtl/math.cxx                  |   67 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)

New commits:
commit a3f5f4f6369552a3da870de1ed4ea9d8c628c7a8
Author: Eike Rathke <erack at redhat.com>
Date:   Wed Jan 13 14:45:29 2016 +0100

    unit test for tdf#96918 display accurate integer double values
    
    Change-Id: I619e0cb0fbbfd0dfba3b2fe9c3476be55a3eea8e

diff --git a/sal/qa/rtl/math/test-rtl-math.cxx b/sal/qa/rtl/math/test-rtl-math.cxx
index aa7b213..6636934 100644
--- a/sal/qa/rtl/math/test-rtl-math.cxx
+++ b/sal/qa/rtl/math/test-rtl-math.cxx
@@ -88,6 +88,46 @@ public:
         CPPUNIT_ASSERT_EQUAL(0.0, res);
     }
 
+    void test_doubleToString() {
+        double fVal = 999999999999999;
+        sal_Int32 aGroups[3] = { 3, 2, 0 };
+        rtl::OUString aRes( rtl::math::doubleToUString( fVal,
+                    rtl_math_StringFormat_Automatic,
+                    rtl_math_DecimalPlaces_Max,
+                    '.', aGroups, ',', true));
+        CPPUNIT_ASSERT_EQUAL( OUString("99,99,99,99,99,99,999"), aRes);
+
+        fVal = 4503599627370495;
+        aRes = rtl::math::doubleToUString( fVal,
+                    rtl_math_StringFormat_Automatic,
+                    rtl_math_DecimalPlaces_Max, '.', false);
+        CPPUNIT_ASSERT_EQUAL( OUString("4503599627370495"), aRes);
+
+        fVal = 4503599627370496;
+        aRes = rtl::math::doubleToUString( fVal,
+                    rtl_math_StringFormat_Automatic,
+                    2, '.', false);
+        CPPUNIT_ASSERT_EQUAL( OUString("4503599627370496.00"), aRes);
+
+        fVal = 9007199254740991;    // (2^53)-1
+        aRes = rtl::math::doubleToUString( fVal,
+                    rtl_math_StringFormat_Automatic,
+                    rtl_math_DecimalPlaces_Max, '.', true);
+        CPPUNIT_ASSERT_EQUAL( OUString("9007199254740991"), aRes);
+
+        fVal = 9007199254740992;    // (2^53), algorithm switch
+        aRes = rtl::math::doubleToUString( fVal,
+                    rtl_math_StringFormat_Automatic,
+                    rtl_math_DecimalPlaces_Max, '.', true);
+        CPPUNIT_ASSERT_EQUAL( OUString("9.00719925474099E+015"), aRes);
+
+        fVal = 9007199254740993;    // (2^53)+1 would be but is 9007199254740992
+        aRes = rtl::math::doubleToUString( fVal,
+                    rtl_math_StringFormat_Automatic,
+                    rtl_math_DecimalPlaces_Max, '.', true);
+        CPPUNIT_ASSERT_EQUAL( OUString("9.00719925474099E+015"), aRes);
+    }
+
     void test_erf() {
         double x, res;
         x =  0.0;
@@ -176,6 +216,7 @@ public:
     CPPUNIT_TEST(test_stringToDouble_good);
     CPPUNIT_TEST(test_stringToDouble_bad);
     CPPUNIT_TEST(test_stringToDouble_exponent_without_digit);
+    CPPUNIT_TEST(test_doubleToString);
     CPPUNIT_TEST(test_erf);
     CPPUNIT_TEST(test_erfc);
     CPPUNIT_TEST(test_expm1);
commit 0f6203edf74832f84d8263d7a544d679203a4efc
Author: Eike Rathke <erack at redhat.com>
Date:   Wed Jan 13 14:40:12 2016 +0100

    tdf#96918 display accurate integer double values up to (2^53)-1
    
    Change-Id: I42001583c72bc3faab94489a4eabfa183cab5ae2

diff --git a/sal/rtl/math.cxx b/sal/rtl/math.cxx
index be8ebbe..45d07b7 100644
--- a/sal/rtl/math.cxx
+++ b/sal/rtl/math.cxx
@@ -207,6 +207,73 @@ inline void doubleToString(StringT ** pResult,
         return;
     }
 
+    // Use integer representation for integer values that fit into the
+    // mantissa (1.((2^53)-1)) with a precision of 1 for highest accuracy.
+    const sal_Int64 kMaxInt = (static_cast<sal_Int64>(1) << 53) - 1;
+    if ((eFormat == rtl_math_StringFormat_Automatic ||
+         eFormat == rtl_math_StringFormat_F) && fValue <= static_cast<double>(kMaxInt))
+    {
+        sal_Int64 nInt = static_cast<sal_Int64>(fValue);
+        // Check the integer range again because double comparison may yield
+        // true within the precision range.
+        if (nInt <= kMaxInt && static_cast<double>(nInt) == fValue)
+        {
+            if (nDecPlaces == rtl_math_DecimalPlaces_Max || bEraseTrailingDecZeros)
+                nDecPlaces = 0;
+            else
+                nDecPlaces = ::std::min( nDecPlaces, 15);
+
+            // Max 1 sign, 16 integer digits, 15 group separators, 1 decimal
+            // separator, 15 decimals digits.
+            typename T::Char aBuf[64];
+            typename T::Char * pBuf = aBuf;
+            typename T::Char * p = pBuf;
+
+            // Backward fill.
+            size_t nGrouping = 0;
+            sal_Int32 nGroupDigits = 0;
+            do
+            {
+                typename T::Char nDigit = nInt % 10;
+                nInt /= 10;
+                *p++ = nDigit + '0';
+                if (pGroups && pGroups[nGrouping] == ++nGroupDigits && nInt > 0 && cGroupSeparator)
+                {
+                    *p++ = cGroupSeparator;
+                    if (pGroups[nGrouping+1])
+                        ++nGrouping;
+                    nGroupDigits = 0;
+                }
+            }
+            while (nInt > 0);
+            if (bSign)
+                *p++ = '-';
+
+            // Reverse buffer content.
+            sal_Int32 n = (p - pBuf) / 2;
+            for (sal_Int32 i=0; i < n; ++i)
+            {
+                typename T::Char c = p[-i-1];
+                p[-i-1] = pBuf[i];
+                pBuf[i] = c;
+            }
+            // Append decimals.
+            if (nDecPlaces)
+            {
+                *p++ = cDecSeparator;
+                while (nDecPlaces--)
+                    *p++ = '0';
+            }
+
+            if (pResultCapacity == nullptr)
+                T::createString(pResult, pBuf, p - pBuf);
+            else
+                T::appendChars(pResult, pResultCapacity, &nResultOffset, pBuf, p - pBuf);
+
+            return;
+        }
+    }
+
     // find the exponent
     int nExp = 0;
     if ( fValue > 0.0 )


More information about the Libreoffice-commits mailing list