[Libreoffice-commits] core.git: include/rtl libreofficekit/source sal/rtl sal/util

Eike Rathke erack at redhat.com
Sat Oct 1 23:03:52 UTC 2016


 include/rtl/math.h                       |    8 ++++++
 include/rtl/math.hxx                     |   14 ++---------
 libreofficekit/source/gtk/lokdocview.cxx |   22 ++++++++++++++++-
 sal/rtl/math.cxx                         |   39 +++++++++++++++++++++++++++++++
 sal/util/sal.map                         |    1 
 5 files changed, 72 insertions(+), 12 deletions(-)

New commits:
commit 2135eae2a97c17d89cb47a2074830fd2d7b2226f
Author: Eike Rathke <erack at redhat.com>
Date:   Sat Oct 1 12:11:19 2016 +0200

    let approxEqual() not scale too early for large representable integer values
    
    And since this is now too much code for inline move implementation to math.cxx
    Which again made it necessary to give libreofficekit lokdocview.cxx its own
    implementation that doesn't even claim to build against sal ...
    
    Change-Id: I0f80be9d9172ee20693b9babde715206f2c3d8c1
    Reviewed-on: https://gerrit.libreoffice.org/29428
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Jenkins <ci at libreoffice.org>

diff --git a/include/rtl/math.h b/include/rtl/math.h
index 41047e1..1217e65 100644
--- a/include/rtl/math.h
+++ b/include/rtl/math.h
@@ -422,6 +422,14 @@ SAL_DLLPUBLIC double SAL_CALL rtl_math_pow10Exp(double fValue, int nExp) SAL_THR
   */
 SAL_DLLPUBLIC double SAL_CALL rtl_math_approxValue(double fValue) SAL_THROW_EXTERN_C();
 
+/** Test equality of two values with an accuracy of the magnitude of the
+    given values scaled by 2^-48 (4 bits roundoff stripped).
+
+    @attention
+    approxEqual( value!=0.0, 0.0 ) _never_ yields true.
+ */
+SAL_DLLPUBLIC bool SAL_CALL rtl_math_approxEqual(double a, double b) SAL_THROW_EXTERN_C();
+
 /** Returns more accurate e^x-1 for x near 0 than calculating directly.
 
     expm1 is part of the C99 standard, but not provided by some compilers.
diff --git a/include/rtl/math.hxx b/include/rtl/math.hxx
index 642763d..fed674f 100644
--- a/include/rtl/math.hxx
+++ b/include/rtl/math.hxx
@@ -239,20 +239,11 @@ inline double acosh(double fValue)
     return rtl_math_acosh(fValue);
 }
 
-
-/** Test equality of two values with an accuracy of the magnitude of the
-    given values scaled by 2^-48 (4 bits roundoff stripped).
-
-    @attention
-    approxEqual( value!=0.0, 0.0 ) _never_ yields true.
+/** A wrapper around rtl_math_approxEqual.
  */
 inline bool approxEqual(double a, double b)
 {
-    if ( a == b )
-        return true;
-    double x = a - b;
-    return (x < 0.0 ? -x : x)
-        < ((a < 0.0 ? -a : a) * (1.0 / (16777216.0 * 16777216.0)));
+    return rtl_math_approxEqual( a, b );
 }
 
 /** Test equality of two values with an accuracy defined by nPrec
@@ -268,6 +259,7 @@ inline bool approxEqual(double a, double b, sal_Int16 nPrec)
     return (x < 0.0 ? -x : x)
         < ((a < 0.0 ? -a : a) * (1.0 / (pow(static_cast<double>(2.0), nPrec))));
 }
+
 /** Add two values.
 
     If signs differ and the absolute values are equal according to approxEqual()
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 0362d25..4d34428 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -3179,6 +3179,26 @@ lok_doc_view_set_visible_area (LOKDocView* pDocView, GdkRectangle* pVisibleArea)
     priv->m_bVisibleAreaSet = true;
 }
 
+namespace {
+// This used to be rtl::math::approxEqual() but since that isn't inline anymore
+// in rtl/math.hxx and was moved into libuno_sal as rtl_math_approxEqual() to
+// cater for representable integer cases and we don't want to link against
+// libuno_sal, we'll have to have an own implementation. The special large
+// integer cases seems not be needed here.
+inline bool lok_approxEqual(double a, double b)
+{
+    static const double e48 = 1.0 / (16777216.0 * 16777216.0);
+    // XXX loplugin:fpcomparison complains about floating-point comparison for
+    // a==b, though we actually want this here.
+    if (!(a<b) && !(a>b))
+        return true;
+    if (a == 0.0 || b == 0.0)
+        return false;
+    const double d = fabs(a - b);
+    return (d < fabs(a) * e48 && d < fabs(b) * e48);
+}
+}
+
 SAL_DLLPUBLIC_EXPORT void
 lok_doc_view_set_zoom (LOKDocView* pDocView, float fZoom)
 {
@@ -3192,7 +3212,7 @@ lok_doc_view_set_zoom (LOKDocView* pDocView, float fZoom)
     fZoom = fZoom < MIN_ZOOM ? MIN_ZOOM : fZoom;
     fZoom = fZoom > MAX_ZOOM ? MAX_ZOOM : fZoom;
 
-    if (rtl::math::approxEqual(fZoom, priv->m_fZoom))
+    if (lok_approxEqual(fZoom, priv->m_fZoom))
         return;
 
     priv->m_fZoom = fZoom;
diff --git a/sal/rtl/math.cxx b/sal/rtl/math.cxx
index b8a1cd2..1df123bb 100644
--- a/sal/rtl/math.cxx
+++ b/sal/rtl/math.cxx
@@ -149,6 +149,27 @@ struct UStringTraits
     }
 };
 
+/** If value (passed as absolute value) is an integer representable as double,
+    which we handle explicitly at some places.
+ */
+bool isRepresentableInteger(double fAbsValue)
+{
+    const sal_Int64 kMaxInt = (static_cast<sal_Int64>(1) << 53) - 1;
+    if (fAbsValue <= static_cast<double>(kMaxInt))
+    {
+        sal_Int64 nInt = static_cast<sal_Int64>(fAbsValue);
+        // Check the integer range again because double comparison may yield
+        // true within the precision range.
+        // XXX loplugin:fpcomparison complains about floating-point comparison
+        // for static_cast<double>(nInt) == fAbsValue, though we actually want
+        // this here.
+        double fInt;
+        return (nInt <= kMaxInt &&
+                (!((fInt = static_cast<double>(nInt)) < fAbsValue) && !(fInt > fAbsValue)));
+    }
+    return false;
+}
+
 // Solaris C++ 5.2 compiler has problems when "StringT ** pResult" is
 // "typename T::String ** pResult" instead:
 template< typename T, typename StringT >
@@ -1064,6 +1085,24 @@ double SAL_CALL rtl_math_approxValue( double fValue ) SAL_THROW_EXTERN_C()
     return bSign ? -fValue : fValue;
 }
 
+bool SAL_CALL rtl_math_approxEqual(double a, double b) SAL_THROW_EXTERN_C()
+{
+    static const double e48 = 1.0 / (16777216.0 * 16777216.0);
+    static const double e44 = e48 * 16.0;
+    // XXX loplugin:fpcomparison complains about floating-point comparison for
+    // a==b, though we actually want this here.
+    if (!(a<b) && !(a>b))
+        return true;
+    if (a == 0.0 || b == 0.0)
+        return false;
+    const double d = fabs(a - b);
+    if (d > ((a = fabs(a)) * e44) || d > ((b = fabs(b)) * e44))
+        return false;
+    if (isRepresentableInteger(d) && isRepresentableInteger(a) && isRepresentableInteger(b))
+        return false;   // special case for representable integers.
+    return (d < a * e48 && d < b * e48);
+}
+
 double SAL_CALL rtl_math_expm1( double fValue ) SAL_THROW_EXTERN_C()
 {
     return expm1(fValue);
diff --git a/sal/util/sal.map b/sal/util/sal.map
index d9995e1e..d50752c 100644
--- a/sal/util/sal.map
+++ b/sal/util/sal.map
@@ -704,6 +704,7 @@ LIBO_UDK_5.3 { # symbols available in >= LibO 5.3
         rtl_uString_newReplaceFirstAsciiLUtf16L;
         rtl_uString_newReplaceFirstUtf16LAsciiL;
         rtl_uString_newReplaceFirstUtf16LUtf16L;
+        rtl_math_approxEqual;
 } LIBO_UDK_5.2;
 
 PRIVATE_1.0 {


More information about the Libreoffice-commits mailing list