[Libreoffice-commits] core.git: sc/inc

dante (via logerrit) logerrit at kemper.freedesktop.org
Mon Apr 26 10:51:47 UTC 2021


 sc/inc/kahan.hxx |  136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 sc/inc/math.hxx  |    1 
 2 files changed, 137 insertions(+)

New commits:
commit 9c4e0c35d70659097b235028047efcb80dcfb10d
Author:     dante <dante19031999 at gmail.com>
AuthorDate: Fri Apr 23 20:04:11 2021 +0200
Commit:     Mike Kaganski <mike.kaganski at collabora.com>
CommitDate: Mon Apr 26 12:51:11 2021 +0200

    Add a Kahan summation class.
    
    Change-Id: I4021d07a2c011c2d5b2e79ecd878019d29cabd21
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114567
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>

diff --git a/sc/inc/kahan.hxx b/sc/inc/kahan.hxx
new file mode 100644
index 000000000000..45b59617e2b7
--- /dev/null
+++ b/sc/inc/kahan.hxx
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+/**
+  * This class provides LO with Kahan summation algorithm
+  * About this algorithm: https://en.wikipedia.org/wiki/Kahan_summation_algorithm
+  * For general purpose software we assume first order error is enough.
+  * This class could be made constexpr if needed.
+  */
+
+class KahanSum
+{
+public:
+    constexpr KahanSum() = default;
+
+    constexpr KahanSum(double x_0)
+        : m_fSum(x_0)
+    {
+    }
+
+    constexpr KahanSum(const KahanSum& fSum) = default;
+
+public:
+    /**
+      * Adds a value to the sum using Kahan sumation.
+      * @param x_i
+      */
+    void add(double x_i)
+    {
+        double t = m_fSum + x_i;
+        if (std::abs(m_fSum) >= std::abs(x_i))
+            m_fError += (m_fSum - t) + x_i;
+        else
+            m_fError += (x_i - t) + m_fSum;
+        m_fSum = t;
+    }
+
+    /**
+      * Adds a value to the sum using Kahan sumation.
+      * @param fSum
+      */
+    inline void add(const KahanSum& fSum)
+    {
+        add(fSum.m_fSum);
+        add(fSum.m_fError);
+    }
+
+public:
+    constexpr KahanSum operator-() const
+    {
+        KahanSum fKahanSum;
+        fKahanSum.m_fSum = -m_fSum;
+        fKahanSum.m_fError = -m_fError;
+        return fKahanSum;
+    }
+
+    constexpr KahanSum& operator=(double fSum)
+    {
+        m_fSum = fSum;
+        m_fError = 0;
+        return *this;
+    }
+
+    constexpr KahanSum& operator=(const KahanSum& fSum) = default;
+
+    inline void operator+=(const KahanSum& fSum) { add(fSum); }
+
+    inline void operator+=(double fSum) { add(fSum); }
+
+    inline void operator-=(const KahanSum& fSum) { add(-fSum); }
+
+    inline void operator-=(double fSum) { add(-fSum); }
+
+    /**
+      * In some parts of the code of interpr_.cxx this may be used for
+      * productory instead of sum. This operator shall be used for that task.
+      */
+    constexpr void operator*=(double fTimes)
+    {
+        m_fSum *= fTimes;
+        m_fError *= fTimes;
+    }
+
+    constexpr void operator/=(double fDivides)
+    {
+        m_fSum /= fDivides;
+        m_fError /= fDivides;
+    }
+
+    constexpr bool operator<(const KahanSum& fSum) const { return get() < fSum.get(); }
+
+    constexpr bool operator<(double fSum) const { return get() < fSum; }
+
+    constexpr bool operator>(const KahanSum& fSum) const { return get() > fSum.get(); }
+
+    constexpr bool operator>(double fSum) const { return get() > fSum; }
+
+    constexpr bool operator<=(const KahanSum& fSum) const { return get() <= fSum.get(); }
+
+    constexpr bool operator<=(double fSum) const { return get() <= fSum; }
+
+    constexpr bool operator>=(const KahanSum& fSum) const { return get() >= fSum.get(); }
+
+    constexpr bool operator>=(double fSum) const { return get() >= fSum; }
+
+    constexpr bool operator==(const KahanSum& fSum) const
+    {
+        return fSum.m_fSum == m_fSum && fSum.m_fError == m_fError;
+    }
+
+    constexpr bool operator!=(const KahanSum& fSum) const
+    {
+        return fSum.m_fSum != m_fSum || fSum.m_fError != m_fError;
+    }
+
+public:
+    /**
+      * Returns the final sum.
+      * @return final sum
+      */
+    constexpr double get() const { return m_fSum + m_fError; }
+
+private:
+    double m_fSum = 0;
+    double m_fError = 0;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sc/inc/math.hxx b/sc/inc/math.hxx
index 2e2ffe0f4bb6..459b82e74bcd 100644
--- a/sc/inc/math.hxx
+++ b/sc/inc/math.hxx
@@ -21,6 +21,7 @@
 
 #include <formula/errorcodes.hxx>
 #include <rtl/math.hxx>
+#include "kahan.hxx"
 
 namespace sc {
 


More information about the Libreoffice-commits mailing list