[Libreoffice-commits] core.git: Branch 'libreoffice-7-1' - include/sal sal/rtl

Eike Rathke (via logerrit) logerrit at kemper.freedesktop.org
Fri Dec 18 10:01:30 UTC 2020


 include/sal/mathconf.h |   14 +++++
 sal/rtl/math.cxx       |  135 +++++++++++++++++++++++++------------------------
 2 files changed, 85 insertions(+), 64 deletions(-)

New commits:
commit ead1cdd23f5379f5cd8f69d5e73f410a67896db2
Author:     Eike Rathke <erack at redhat.com>
AuthorDate: Thu Dec 17 20:44:43 2020 +0100
Commit:     Eike Rathke <erack at redhat.com>
CommitDate: Fri Dec 18 11:00:57 2020 +0100

    Check intermediate for not to be rounded value, tdf#138360 follow-up
    
     This is a combination of 3 commits.
    
    Add sal_uInt64 fields to sal_math_Double
    
    We may need them later, and at least don't have a confusing
    inf_parts or nan_parts struct name but just parts as well.
    
    Ife0cf279c47d2815aa2a1483223397b147e9d776
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107924
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Jenkins
    
    Replace log2() call with parts.exponent-1023, tdf#138360 follow-up
    
    ... to save some cycles as we anyway need only the integer value
    of the exponent and even exactly this value for the number of
    possible decimals.
    
    I8d462f53cadde6a95d57d1342d8487fbfa001ae9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107928
    Tested-by: Jenkins
    Reviewed-by: Eike Rathke <erack at redhat.com>
    
    Check intermediate for not to be rounded value, tdf#138360 follow-up
    
    I98cc25267e7a10c34179bab50d19f49436e1c48c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107929
    Tested-by: Jenkins
    Reviewed-by: Eike Rathke <erack at redhat.com>
    
    Change-Id: I98cc25267e7a10c34179bab50d19f49436e1c48c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107931
    Tested-by: Jenkins
    Reviewed-by: Eike Rathke <erack at redhat.com>

diff --git a/include/sal/mathconf.h b/include/sal/mathconf.h
index 687f6e3da133..11bd32c35de0 100644
--- a/include/sal/mathconf.h
+++ b/include/sal/mathconf.h
@@ -104,6 +104,13 @@ union sal_math_Double
         unsigned msw          :32;
         unsigned lsw          :32;
     } w32_parts;
+    struct
+    {
+        sal_uInt64 sign       : 1;
+        sal_uInt64 exponent   :11;
+        sal_uInt64 fraction   :52;
+    } parts;
+    sal_uInt64 intrep;
     double value;
 };
 
@@ -130,6 +137,13 @@ union sal_math_Double
         unsigned lsw          :32;
         unsigned msw          :32;
     } w32_parts;
+    struct
+    {
+        sal_uInt64 fraction   :52;
+        sal_uInt64 exponent   :11;
+        sal_uInt64 sign       : 1;
+    } parts;
+    sal_uInt64 intrep;
     double value;
 };
 
diff --git a/sal/rtl/math.cxx b/sal/rtl/math.cxx
index 46a3e925b95b..a85c8ac6e959 100644
--- a/sal/rtl/math.cxx
+++ b/sal/rtl/math.cxx
@@ -1167,9 +1167,10 @@ double SAL_CALL rtl_math_round(double fValue, int nDecPlaces,
             // Determine how many decimals are representable in the precision.
             // Anything greater 2^52 and 0.0 was already ruled out above.
             // Theoretically 0.5, 0.25, 0.125, 0.0625, 0.03125, ...
-            const double fDec = 52 - log2(fValue) + 1;
-            if (fDec < nDecPlaces)
-                nDecPlaces = static_cast<sal_Int32>(fDec);
+            const sal_math_Double* pd = reinterpret_cast<const sal_math_Double*>(&fValue);
+            const sal_Int32 nDec = 52 - (pd->parts.exponent - 1023);
+            if (nDec < nDecPlaces)
+                nDecPlaces = nDec;
         }
 
         /* TODO: this was without the inverse factor and determining max
@@ -1190,75 +1191,81 @@ double SAL_CALL rtl_math_round(double fValue, int nDecPlaces,
             fValue *= fFac;
     }
 
-    switch ( eMode )
+    // Round only if not already in distance precision gaps of integers, where
+    // for [2^52,2^53) adding 0.5 would even yield the next representable
+    // integer.
+    if (fValue < (static_cast<sal_Int64>(1) << 52))
     {
-        case rtl_math_RoundingMode_Corrected :
-            fValue = rtl::math::approxFloor(fValue + 0.5);
-        break;
-        case rtl_math_RoundingMode_Down:
-            fValue = rtl::math::approxFloor(fValue);
-        break;
-        case rtl_math_RoundingMode_Up:
-            fValue = rtl::math::approxCeil(fValue);
-        break;
-        case rtl_math_RoundingMode_Floor:
-            fValue = bSign ? rtl::math::approxCeil(fValue)
-                : rtl::math::approxFloor( fValue );
-        break;
-        case rtl_math_RoundingMode_Ceiling:
-            fValue = bSign ? rtl::math::approxFloor(fValue)
-                : rtl::math::approxCeil(fValue);
-        break;
-        case rtl_math_RoundingMode_HalfDown :
-        {
-            double f = floor(fValue);
-            fValue = ((fValue - f) <= 0.5) ? f : ceil(fValue);
-        }
-        break;
-        case rtl_math_RoundingMode_HalfUp:
+        switch ( eMode )
         {
-            double f = floor(fValue);
-            fValue = ((fValue - f) < 0.5) ? f : ceil(fValue);
-        }
-        break;
-        case rtl_math_RoundingMode_HalfEven:
+            case rtl_math_RoundingMode_Corrected :
+                fValue = rtl::math::approxFloor(fValue + 0.5);
+            break;
+            case rtl_math_RoundingMode_Down:
+                fValue = rtl::math::approxFloor(fValue);
+            break;
+            case rtl_math_RoundingMode_Up:
+                fValue = rtl::math::approxCeil(fValue);
+            break;
+            case rtl_math_RoundingMode_Floor:
+                fValue = bSign ? rtl::math::approxCeil(fValue)
+                    : rtl::math::approxFloor( fValue );
+            break;
+            case rtl_math_RoundingMode_Ceiling:
+                fValue = bSign ? rtl::math::approxFloor(fValue)
+                    : rtl::math::approxCeil(fValue);
+            break;
+            case rtl_math_RoundingMode_HalfDown :
+                {
+                    double f = floor(fValue);
+                    fValue = ((fValue - f) <= 0.5) ? f : ceil(fValue);
+                }
+            break;
+            case rtl_math_RoundingMode_HalfUp:
+                {
+                    double f = floor(fValue);
+                    fValue = ((fValue - f) < 0.5) ? f : ceil(fValue);
+                }
+            break;
+            case rtl_math_RoundingMode_HalfEven:
 #if defined FLT_ROUNDS
-/*
-    Use fast version. FLT_ROUNDS may be defined to a function by some compilers!
-
-    DBL_EPSILON is the smallest fractional number which can be represented,
-    its reciprocal is therefore the smallest number that cannot have a
-    fractional part. Once you add this reciprocal to `x', its fractional part
-    is stripped off. Simply subtracting the reciprocal back out returns `x'
-    without its fractional component.
-    Simple, clever, and elegant - thanks to Ross Cottrell, the original author,
-    who placed it into public domain.
-
-    volatile: prevent compiler from being too smart
-*/
-            if (FLT_ROUNDS == 1)
-            {
-                volatile double x = fValue + 1.0 / DBL_EPSILON;
-                fValue = x - 1.0 / DBL_EPSILON;
-            }
-            else
-#endif // FLT_ROUNDS
-            {
-                double f = floor(fValue);
-                if ((fValue - f) != 0.5)
+                /*
+                   Use fast version. FLT_ROUNDS may be defined to a function by some compilers!
+
+                   DBL_EPSILON is the smallest fractional number which can be represented,
+                   its reciprocal is therefore the smallest number that cannot have a
+                   fractional part. Once you add this reciprocal to `x', its fractional part
+                   is stripped off. Simply subtracting the reciprocal back out returns `x'
+                   without its fractional component.
+                   Simple, clever, and elegant - thanks to Ross Cottrell, the original author,
+                   who placed it into public domain.
+
+                   volatile: prevent compiler from being too smart
+                */
+                if (FLT_ROUNDS == 1)
                 {
-                    fValue = floor( fValue + 0.5 );
+                    volatile double x = fValue + 1.0 / DBL_EPSILON;
+                    fValue = x - 1.0 / DBL_EPSILON;
                 }
                 else
+#endif // FLT_ROUNDS
                 {
-                    double g = f / 2.0;
-                    fValue = (g == floor( g )) ? f : (f + 1.0);
+                    double f = floor(fValue);
+                    if ((fValue - f) != 0.5)
+                    {
+                        fValue = floor( fValue + 0.5 );
+                    }
+                    else
+                    {
+                        double g = f / 2.0;
+                        fValue = (g == floor( g )) ? f : (f + 1.0);
+                    }
                 }
-            }
-        break;
-        default:
-            OSL_ASSERT(false);
-        break;
+            break;
+            default:
+                OSL_ASSERT(false);
+            break;
+        }
     }
 
     if (nDecPlaces != 0)


More information about the Libreoffice-commits mailing list