[Libreoffice-commits] core.git: Branch 'libreoffice-6-2' - 2 commits - sc/inc sc/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Tue Dec 11 21:24:27 UTC 2018


 sc/inc/dpglobal.hxx              |    2 +-
 sc/inc/subtotal.hxx              |   23 ++++++++++++++++++++++-
 sc/source/core/data/column2.cxx  |   14 ++++++++++++--
 sc/source/core/data/documen4.cxx |   39 ++++++++++++++++++++++++++++++++++++---
 sc/source/core/tool/subtotal.cxx |    8 ++++++++
 5 files changed, 79 insertions(+), 7 deletions(-)

New commits:
commit 80fdc2491df857c910afbd30c025b4594cb1cf83
Author:     Eike Rathke <erack at redhat.com>
AuthorDate: Tue Dec 11 17:35:00 2018 +0100
Commit:     Eike Rathke <erack at redhat.com>
CommitDate: Tue Dec 11 22:24:16 2018 +0100

    Correct typed_flags<PivotFunc> mask is 0x1fff
    
    This was wrong since
    
        commit 298ee50676b849020a8a5042e8612f71379ecf3b
        CommitDate: Sun Nov 20 00:14:28 2016 +0100
    
            PivotMedian: Implement median as a new pivot table function
    
    and in fact in a debug build failed an assertion
    
    soffice.bin: include/o3tl/typed_flags_set.hxx:85:
      constexpr o3tl::is_typed_flags<E, M>::Wrap::Wrap(type name std::underlying_type<_Tp>::type)
      [with E = PivotFunc; typename std::underlying_type<_Tp>::type M = 4607; typename std::underlying_type<_Tp>::type = int]:
      Assertion `static_cast<typename std::underlying_type<E>::type>(~0) == M || (value & ~M) == 0' failed.
    
    when one of the functions (e.g. StdVar) not included in the mask
    was chosen as pivot table data function.
    
    Change-Id: I5b9efc7d2cbcf6fece3ef228db8f6e0ffa17b510
    Reviewed-on: https://gerrit.libreoffice.org/64974
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 639a401fbd910c1fede35f7106a5acf716ec5fea)
    Reviewed-on: https://gerrit.libreoffice.org/64984

diff --git a/sc/inc/dpglobal.hxx b/sc/inc/dpglobal.hxx
index 295af86db148..0a5b6e94dc6b 100644
--- a/sc/inc/dpglobal.hxx
+++ b/sc/inc/dpglobal.hxx
@@ -39,7 +39,7 @@ enum class PivotFunc {
     Auto         = 0x1000
 };
 namespace o3tl {
-    template<> struct typed_flags<PivotFunc> : is_typed_flags<PivotFunc, 0x11ff> {};
+    template<> struct typed_flags<PivotFunc> : is_typed_flags<PivotFunc, 0x1fff> {};
 }
 
 struct ScDPValue
commit 1cb79dd63e0f825cee46fa58a6a9df39e8160f60
Author:     Eike Rathke <erack at redhat.com>
AuthorDate: Tue Dec 11 12:43:14 2018 +0100
Commit:     Eike Rathke <erack at redhat.com>
CommitDate: Tue Dec 11 22:24:03 2018 +0100

    Resolves: tdf#46119 implement GeneralFunction_VAR, VARP, STDEV and STDEVP
    
    These were never implemented. Likely because they aren't used
    internally by Calc, which for formula expressions in the
    interpreter and for DataPilot / pivot table uses a different
    approach, but they are needed for
    css::sheet::XSheetOperation::computeFunction()
    
    Change-Id: I1af038bf9db8d0c04d69598b992b827b083e2248
    Reviewed-on: https://gerrit.libreoffice.org/64957
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit fc1568d570a96bfa57013ae62adf3f9606639fd3)
    Reviewed-on: https://gerrit.libreoffice.org/64975

diff --git a/sc/inc/subtotal.hxx b/sc/inc/subtotal.hxx
index 7858fcae6f2b..46f6fcc7693c 100644
--- a/sc/inc/subtotal.hxx
+++ b/sc/inc/subtotal.hxx
@@ -30,11 +30,32 @@ public:
     static bool SafeDiv( double& fVal1, double fVal2);
 };
 
+/** Implements the Welford Online one-pass algorithm.
+    See https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_Online_algorithm
+    and Donald E. Knuth, TAoCP vol.2, 3rd edn., p. 232
+ */
+class WelfordRunner
+{
+public:
+    WelfordRunner() : fMean(0.0), fM2(0.0), nCount(0) {}
+    void        update( double fVal );
+    sal_uInt64  getCount() const                { return nCount; }
+    double      getMean() const                 { return fMean; }
+    double      getVarianceSample() const       { return nCount > 1 ? fM2 / (nCount-1) : 0.0; }
+    double      getVariancePopulation() const   { return nCount > 0 ? fM2 / nCount : 0.0; }
+
+private:
+    double      fMean;
+    double      fM2;
+    sal_Int64   nCount;
+};
+
 struct ScFunctionData                   // to calculate single functions
 {
+    WelfordRunner   maWelford;
     ScSubTotalFunc const  eFunc;
     double          nVal;
-    long            nCount;
+    sal_uInt64      nCount;
     bool            bError;
 
     ScFunctionData( ScSubTotalFunc eFn ) :
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index c46f1a70ce8b..5f77628699f6 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -3423,10 +3423,20 @@ class UpdateSubTotalHandler
                     mrData.nVal = fVal;
             }
             break;
-            default:
+            case SUBTOTAL_FUNC_VAR:
+            case SUBTOTAL_FUNC_VARP:
+            case SUBTOTAL_FUNC_STD:
+            case SUBTOTAL_FUNC_STDP:
             {
-                // added to avoid warnings
+                if (!bVal)
+                    return;
+
+                mrData.maWelford.update( fVal);
             }
+            break;
+            default:
+                // unhandled unknown
+                mrData.bError = true;
         }
     }
 
diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx
index 9e4cc23cb85d..94b361cde765 100644
--- a/sc/source/core/data/documen4.cxx
+++ b/sc/source/core/data/documen4.cxx
@@ -642,10 +642,43 @@ bool ScDocument::GetSelectionFunction( ScSubTotalFunc eFunc,
                 else
                     aData.bError = true;
                 break;
+            case SUBTOTAL_FUNC_VAR:
+            case SUBTOTAL_FUNC_STD:
+                if (aData.maWelford.getCount() < 2)
+                    aData.bError = true;
+                else
+                {
+                    rResult = aData.maWelford.getVarianceSample();
+                    if (eFunc == SUBTOTAL_FUNC_STD)
+                    {
+                        if (rResult < 0.0)
+                            aData.bError = true;
+                        else
+                            rResult = sqrt( rResult);
+                    }
+                }
+                break;
+            case SUBTOTAL_FUNC_VARP:
+            case SUBTOTAL_FUNC_STDP:
+                if (aData.maWelford.getCount() < 1)
+                    aData.bError = true;
+                else if (aData.maWelford.getCount() == 1)
+                    rResult = 0.0;
+                else
+                {
+                    rResult = aData.maWelford.getVariancePopulation();
+                    if (eFunc == SUBTOTAL_FUNC_STDP)
+                    {
+                        if (rResult < 0.0)
+                            aData.bError = true;
+                        else
+                            rResult = sqrt( rResult);
+                    }
+                }
+                break;
             default:
-            {
-                // added to avoid warnings
-            }
+                // unhandled unknown
+                aData.bError = true;
         }
 
     if (aData.bError)
diff --git a/sc/source/core/tool/subtotal.cxx b/sc/source/core/tool/subtotal.cxx
index f57d0ae1d8d4..ec908b16eeec 100644
--- a/sc/source/core/tool/subtotal.cxx
+++ b/sc/source/core/tool/subtotal.cxx
@@ -62,4 +62,12 @@ bool SubTotal::SafeDiv(double& fVal1, double fVal2)
     return bOk;
 }
 
+void WelfordRunner::update( double fVal )
+{
+    ++nCount;
+    const double fDelta = fVal - fMean;
+    fMean += fDelta / nCount;
+    fM2 += fDelta * (fVal - fMean);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list