sal/rtl/math.cxx |   78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

New commits:
commit 4c2c161018165b7484233547fea1511c84b3ffe3
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Fri Nov 27 17:38:46 2020 +0100
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Thu Dec 10 15:21:06 2020 +0100

    Resolves: tdf#136272 convert DBL_MAX to 1.7976931348623157e+308
    
     This is a combination of 4 commits.
    
    Resolves: tdf#136272 convert DBL_MAX to 1.7976931348623157e+308
    
    ... and the 4 subsequent nextafters to appropriate strings.
    
    An interim workaround to not write the out-of-range string
    1.79769313486232e+308 until we have a proper rounding.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106717
    Tested-by: Jenkins
    Reviewed-by: Eike Rathke <er...@redhat.com>
    (cherry picked from commit 4713c19e2b79341dc27e66d4c6449497db1e73d8)
    
    Consistently use RTL_CONSTASCII_LENGTH(), tdf#136272 follow-up
    
    The mix with SAL_N_ELEMENTS() was confusing and even wrong in one
    case.
    
    Ife73342b0efc01ed4e76e217d372fc32500c9b2c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106764
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 1a0f9a9c56e7b7952b813b3efd34f9be6c853957)
    
    Fix comment
    
    I2ae6e3cadc0f182c4798e5d33b0c7f07fbcbbff6
    (cherry picked from commit b8404ae521a9c2d183d4e076a7884627ba353e4b)
    
    Typo in rounded digit string, tdf#138360 follow-up
    
    Ic436d3e9f0c93cb36c5e4377519f2aeb6b7fbd5f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107034
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit d8e0b1c81ffa16be8aae2231bcd3c02e8c01cf88)
    
    Change-Id: I5f98a7f0a8e0421fd024a8cc37cc6f3a198d02d1
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106686
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@cib.de>

diff --git a/sal/rtl/math.cxx b/sal/rtl/math.cxx
index 9c32cff30f2f..bd9d2c8a601f 100644
--- a/sal/rtl/math.cxx
+++ b/sal/rtl/math.cxx
@@ -274,6 +274,84 @@ void doubleToString(typename T::String ** pResult,
         return;
     }
 
+    // Unfortunately the old rounding below writes 1.79769313486232e+308 for
+    // DBL_MAX and 4 subsequent nextafter(...,0).
+    static const double fB1 = std::nextafter( DBL_MAX, 0);
+    static const double fB2 = std::nextafter( fB1, 0);
+    static const double fB3 = std::nextafter( fB2, 0);
+    static const double fB4 = std::nextafter( fB3, 0);
+    if ((fValue >= fB4) && eFormat != rtl_math_StringFormat_F)
+    {
+        // 1.7976931348623157e+308 instead of rounded 1.79769313486232e+308
+        // that can't be converted back as out of range. For rounded values if
+        // they exceed range they should not be written to exchange strings or
+        // file formats.
+
+        // Writing pDig up to decimals(-1,-2) then appending one digit from
+        // pRou xor one or two digits from pSlot[].
+        constexpr char pDig[] = "7976931348623157";
+        constexpr char pRou[] = "8087931359623267";     // the only up-carry 
is 80
+        static_assert(SAL_N_ELEMENTS(pDig) == SAL_N_ELEMENTS(pRou), "digit 
count mismatch");
+        constexpr sal_Int32 nDig2 = RTL_CONSTASCII_LENGTH(pRou) - 2;
+        sal_Int32 nCapacity = RTL_CONSTASCII_LENGTH(pRou) + 8;  // + "-1.E+308"
+        const char pSlot[5][2][3] =
+        { // rounded, not
+            "67", "57",     // DBL_MAX
+            "65", "55",
+            "53", "53",
+            "51", "51",
+            "59", "49",
+        };
+
+        if (!pResultCapacity)
+        {
+            pResultCapacity = &nCapacity;
+            T::createBuffer(pResult, pResultCapacity);
+            nResultOffset = 0;
+        }
+
+        if (bSign)
+            T::appendAscii(pResult, pResultCapacity, &nResultOffset,
+                           RTL_CONSTASCII_STRINGPARAM("-"));
+
+        nDecPlaces = std::clamp<sal_Int32>( nDecPlaces, 0, 
RTL_CONSTASCII_LENGTH(pRou));
+        if (nDecPlaces == 0)
+        {
+            T::appendAscii(pResult, pResultCapacity, &nResultOffset,
+                           RTL_CONSTASCII_STRINGPARAM("2"));
+        }
+        else
+        {
+            T::appendAscii(pResult, pResultCapacity, &nResultOffset,
+                           RTL_CONSTASCII_STRINGPARAM("1"));
+            T::appendChars(pResult, pResultCapacity, &nResultOffset, 
&cDecSeparator, 1);
+            if (nDecPlaces <= 2)
+            {
+                T::appendAscii(pResult, pResultCapacity, &nResultOffset, pRou, 
nDecPlaces);
+            }
+            else if (nDecPlaces <= nDig2)
+            {
+                T::appendAscii(pResult, pResultCapacity, &nResultOffset, pDig, 
nDecPlaces - 1);
+                T::appendAscii(pResult, pResultCapacity, &nResultOffset, pRou 
+ nDecPlaces - 1, 1);
+            }
+            else
+            {
+                const sal_Int32 nDec = nDecPlaces - nDig2;
+                nDecPlaces -= nDec;
+                // nDec-1 is also offset into slot, rounded(1-1=0) or 
not(2-1=1)
+                const size_t nSlot = ((fValue < fB3) ? 4 : ((fValue < fB2) ? 3
+                            : ((fValue < fB1) ? 2 : ((fValue < DBL_MAX) ? 1 : 
0))));
+
+                T::appendAscii(pResult, pResultCapacity, &nResultOffset, pDig, 
nDecPlaces);
+                T::appendAscii(pResult, pResultCapacity, &nResultOffset, 
pSlot[nSlot][nDec-1], nDec);
+            }
+        }
+        T::appendAscii(pResult, pResultCapacity, &nResultOffset,
+                       RTL_CONSTASCII_STRINGPARAM("E+308"));
+
+        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;
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to