[Libreoffice-commits] core.git: sc/inc sc/source
Libreoffice Gerrit user
logerrit at kemper.freedesktop.org
Tue Dec 11 16:55:00 UTC 2018
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 ++++++++
4 files changed, 78 insertions(+), 6 deletions(-)
New commits:
commit fc1568d570a96bfa57013ae62adf3f9606639fd3
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 17:54:36 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
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