From a9b71098845edcb4f6b4629795168d174f28ef70 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Tue, 9 Mar 2021 09:44:24 +0100 Subject: tdf#133423 Fix 'central' formula for moving average Change-Id: I3685c310fdbe4809cb7863628be96645364c6a7a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112191 Tested-by: Jenkins Reviewed-by: Samuel Mehrbrodt --- .../inc/MovingAverageRegressionCurveCalculator.hxx | 5 +-- .../MovingAverageRegressionCurveCalculator.cxx | 44 +++++++++++++++++----- 2 files changed, 37 insertions(+), 12 deletions(-) (limited to 'chart2') diff --git a/chart2/source/inc/MovingAverageRegressionCurveCalculator.hxx b/chart2/source/inc/MovingAverageRegressionCurveCalculator.hxx index 8ba5456c2939..8bc76a33762e 100644 --- a/chart2/source/inc/MovingAverageRegressionCurveCalculator.hxx +++ b/chart2/source/inc/MovingAverageRegressionCurveCalculator.hxx @@ -52,9 +52,8 @@ private: const css::uno::Reference& xScalingY, sal_Bool bMaySkipPointsInCalculation ) override; - void calculateValues(RegressionCalculationHelper::tDoubleVectorPair aValues, sal_Int32 nPeriod, - bool bUseXAvg); - + void calculateValues(RegressionCalculationHelper::tDoubleVectorPair aValues, bool bUseXAvg); + void calculateValuesCentral(RegressionCalculationHelper::tDoubleVectorPair aValues); std::vector aYList; std::vector aXList; }; diff --git a/chart2/source/tools/MovingAverageRegressionCurveCalculator.cxx b/chart2/source/tools/MovingAverageRegressionCurveCalculator.cxx index bca154047935..5496f78577e6 100644 --- a/chart2/source/tools/MovingAverageRegressionCurveCalculator.cxx +++ b/chart2/source/tools/MovingAverageRegressionCurveCalculator.cxx @@ -53,45 +53,71 @@ void SAL_CALL MovingAverageRegressionCurveCalculator::recalculateRegression( aYList.clear(); aXList.clear(); + // For formulas, see + // https://docs.oasis-open.org/office/OpenDocument/v1.3/cs02/part3-schema/OpenDocument-v1.3-cs02-part3-schema.html#property-chart_regression-moving-type + switch (mnMovingType) { case MovingAverageType::Central: { - sal_Int32 nCentralPeriod = (mPeriod % 2 == 0) ? (mPeriod / 2) : ((mPeriod - 1) / 2); - calculateValues(aValues, nCentralPeriod, false); + + calculateValuesCentral(aValues); break; } case MovingAverageType::AveragedAbscissa: { - calculateValues(aValues, mPeriod, true); + calculateValues(aValues, true); break; } case MovingAverageType::Prior: default: { - calculateValues(aValues, mPeriod, false); + calculateValues(aValues, false); break; } } } +void MovingAverageRegressionCurveCalculator::calculateValuesCentral( + RegressionCalculationHelper::tDoubleVectorPair aValues) +{ + const size_t aSize = aValues.first.size(); + for (size_t i = mPeriod - 1; i < aSize; ++i) + { + double yAvg = 0.0; + + for (sal_Int32 j = 0; j < mPeriod; j++) + { + yAvg += aValues.second[i - j]; + } + yAvg /= mPeriod; + aYList.push_back(yAvg); + } + sal_Int32 nPeriodLocal = (mPeriod % 2 == 0) ? (mPeriod / 2) : ((mPeriod - 1) / 2); + for (size_t i = nPeriodLocal; i < aSize - 1; ++i) + { + double x = aValues.first[i]; + aXList.push_back(x); + } +} + void MovingAverageRegressionCurveCalculator::calculateValues( - RegressionCalculationHelper::tDoubleVectorPair aValues, sal_Int32 nPeriod, bool bUseXAvg) + RegressionCalculationHelper::tDoubleVectorPair aValues, bool bUseXAvg) { const size_t aSize = aValues.first.size(); - for (size_t i = nPeriod - 1; i < aSize; ++i) + for (size_t i = mPeriod - 1; i < aSize; ++i) { double xAvg = 0.0; double yAvg = 0.0; - for (sal_Int32 j = 0; j < nPeriod; j++) + for (sal_Int32 j = 0; j < mPeriod; j++) { xAvg += aValues.first[i - j]; yAvg += aValues.second[i - j]; } - yAvg /= nPeriod; - xAvg /= nPeriod; + yAvg /= mPeriod; + xAvg /= mPeriod; aYList.push_back(yAvg); if (bUseXAvg) -- cgit v1.2.3