sc/qa/unit/data/functions/statistical/fods/forecast.ets.mult.fods | 22 +-- sc/source/core/tool/interpr8.cxx | 56 +++++----- 2 files changed, 41 insertions(+), 37 deletions(-)
New commits: commit 38c88aca77f8c8ef47470723557ddf9e5d9d7b66 Author: dante <dante19031...@gmail.com> AuthorDate: Wed May 5 10:57:14 2021 +0200 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Fri May 7 14:29:39 2021 +0200 tdf#137679 Use Kahan summation for interpr8.cxx Change-Id: Id43765f7d8f51066da4bbebcfc175a0e69a58fde Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115127 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sc/qa/unit/data/functions/statistical/fods/forecast.ets.mult.fods b/sc/qa/unit/data/functions/statistical/fods/forecast.ets.mult.fods index 0c45eb46cd8c..150ec6b68115 100644 --- a/sc/qa/unit/data/functions/statistical/fods/forecast.ets.mult.fods +++ b/sc/qa/unit/data/functions/statistical/fods/forecast.ets.mult.fods @@ -8555,10 +8555,10 @@ </table:table-cell> </table:table-row> <table:table-row table:style-name="ro7"> - <table:table-cell office:value-type="float" office:value="190.641123921524" calcext:value-type="float"> - <text:p>190.641123921524</text:p> + <table:table-cell office:value-type="float" office:value="190.641123921525" calcext:value-type="float"> + <text:p>190.641123921525</text:p> </table:table-cell> - <table:table-cell table:style-name="ce14" office:value-type="float" office:value="190.641123921524" calcext:value-type="float"> + <table:table-cell table:style-name="ce14" office:value-type="float" office:value="190.641123921525" calcext:value-type="float"> <text:p>190.641124</text:p> </table:table-cell> <table:table-cell table:style-name="ce16" table:formula="of:=ROUND([.A64];12)=ROUND([.B64];12)" office:value-type="boolean" office:boolean-value="true" calcext:value-type="boolean"> @@ -9014,11 +9014,11 @@ </table:table-cell> </table:table-row> <table:table-row table:style-name="ro7"> - <table:table-cell office:value-type="float" office:value="268.59802115122" calcext:value-type="float"> - <text:p>268.59802115122</text:p> + <table:table-cell office:value-type="float" office:value="268.598021151221" calcext:value-type="float"> + <text:p>268.598021151221</text:p> </table:table-cell> - <table:table-cell office:value-type="float" office:value="268.59802115122" calcext:value-type="float"> - <text:p>268.59802115122</text:p> + <table:table-cell office:value-type="float" office:value="268.598021151221" calcext:value-type="float"> + <text:p>268.598021151221</text:p> </table:table-cell> <table:table-cell table:style-name="ce16" table:formula="of:=ROUND([.A79];12)=ROUND([.B79];12)" office:value-type="boolean" office:boolean-value="true" calcext:value-type="boolean"> <text:p>TRUE</text:p> @@ -9196,11 +9196,11 @@ </table:table-cell> </table:table-row> <table:table-row table:style-name="ro7"> - <table:table-cell office:value-type="float" office:value="267.531016699979" calcext:value-type="float"> - <text:p>267.531016699979</text:p> + <table:table-cell office:value-type="float" office:value="267.531016699980" calcext:value-type="float"> + <text:p>267.531016699980</text:p> </table:table-cell> - <table:table-cell office:value-type="float" office:value="267.531016699979" calcext:value-type="float"> - <text:p>267.531016699979</text:p> + <table:table-cell office:value-type="float" office:value="267.531016699980" calcext:value-type="float"> + <text:p>267.531016699980</text:p> </table:table-cell> <table:table-cell table:style-name="ce16" table:formula="of:=ROUND([.A86];12)=ROUND([.B86];12)" office:value-type="boolean" office:boolean-value="true" calcext:value-type="boolean"> <text:p>TRUE</text:p> diff --git a/sc/source/core/tool/interpr8.cxx b/sc/source/core/tool/interpr8.cxx index 750b42572706..64bb3d1d8a8e 100644 --- a/sc/source/core/tool/interpr8.cxx +++ b/sc/source/core/tool/interpr8.cxx @@ -353,9 +353,9 @@ bool ScETSForecastCalculation::PreprocessDataRange( const ScMatrixRef& rMatX, co { // gap, insert missing data points double fYGap = ( maRange[ i ].Y + maRange[ i - 1 ].Y ) / 2.0; - for ( double fXGap = maRange[ i - 1].X + mfStepSize; fXGap < maRange[ i ].X; fXGap += mfStepSize ) + for ( KahanSum fXGap = maRange[ i - 1].X + mfStepSize; fXGap < maRange[ i ].X; fXGap += mfStepSize ) { - maRange.insert( maRange.begin() + i, DataPoint( fXGap, ( bDataCompletion ? fYGap : 0.0 ) ) ); + maRange.insert( maRange.begin() + i, DataPoint( fXGap.get(), ( bDataCompletion ? fYGap : 0.0 ) ) ); i++; mnCount++; nMissingXCount++; @@ -419,10 +419,13 @@ bool ScETSForecastCalculation::prefillTrendData() return false; } - double fSum = 0.0; + KahanSum fSum = 0.0; for ( SCSIZE i = 0; i < mnSmplInPrd; i++ ) - fSum += maRange[ i + mnSmplInPrd ].Y - maRange[ i ].Y; - double fTrend = fSum / static_cast< double >( mnSmplInPrd * mnSmplInPrd ); + { + fSum += maRange[ i + mnSmplInPrd ].Y; + fSum -= maRange[ i ].Y; + } + double fTrend = fSum.get() / static_cast< double >( mnSmplInPrd * mnSmplInPrd ); mpTrend[ 0 ] = fTrend; } @@ -442,7 +445,7 @@ bool ScETSForecastCalculation::prefillPerIdx() return false; } SCSIZE nPeriods = mnCount / mnSmplInPrd; - std::vector< double > aPeriodAverage( nPeriods, 0.0 ); + std::vector< KahanSum > aPeriodAverage( nPeriods, 0.0 ); for ( SCSIZE i = 0; i < nPeriods ; i++ ) { for ( SCSIZE j = 0; j < mnSmplInPrd; j++ ) @@ -458,20 +461,20 @@ bool ScETSForecastCalculation::prefillPerIdx() for ( SCSIZE j = 0; j < mnSmplInPrd; j++ ) { - double fI = 0.0; + KahanSum fI = 0.0; for ( SCSIZE i = 0; i < nPeriods ; i++ ) { // adjust average value for position within period if ( bAdditive ) - fI += ( maRange[ i * mnSmplInPrd + j ].Y - - ( aPeriodAverage[ i ] + ( static_cast< double >( j ) - 0.5 * ( mnSmplInPrd - 1 ) ) * - mpTrend[ 0 ] ) ); + fI += maRange[ i * mnSmplInPrd + j ].Y - + ( aPeriodAverage[ i ].get() + ( static_cast< double >( j ) - 0.5 * ( mnSmplInPrd - 1 ) ) * + mpTrend[ 0 ] ); else - fI += ( maRange[ i * mnSmplInPrd + j ].Y / - ( aPeriodAverage[ i ] + ( static_cast< double >( j ) - 0.5 * ( mnSmplInPrd - 1 ) ) * - mpTrend[ 0 ] ) ); + fI += maRange[ i * mnSmplInPrd + j ].Y / + ( aPeriodAverage[ i ].get() + ( static_cast< double >( j ) - 0.5 * ( mnSmplInPrd - 1 ) ) * + mpTrend[ 0 ] ); } - mpPerIdx[ j ] = fI / nPeriods; + mpPerIdx[ j ] = fI.get() / nPeriods; } if (mnSmplInPrd < mnCount) mpPerIdx[mnSmplInPrd] = 0.0; @@ -500,10 +503,10 @@ void ScETSForecastCalculation::initCalc() void ScETSForecastCalculation::calcAccuracyIndicators() { - double fSumAbsErr = 0.0; - double fSumDivisor = 0.0; - double fSumErrSq = 0.0; - double fSumAbsPercErr = 0.0; + KahanSum fSumAbsErr = 0.0; + KahanSum fSumDivisor = 0.0; + KahanSum fSumErrSq = 0.0; + KahanSum fSumAbsPercErr = 0.0; for ( SCSIZE i = 1; i < mnCount; i++ ) { @@ -517,11 +520,11 @@ void ScETSForecastCalculation::calcAccuracyIndicators() fSumDivisor += fabs( maRange[ i ].Y - maRange[ i - 1 ].Y ); int nCalcCount = mnCount - 1; - mfMAE = fSumAbsErr / nCalcCount; - mfMASE = fSumAbsErr / ( nCalcCount * fSumDivisor / ( nCalcCount - 1 ) ); - mfMSE = fSumErrSq / nCalcCount; + mfMAE = fSumAbsErr.get() / nCalcCount; + mfMASE = fSumAbsErr.get() / ( nCalcCount * fSumDivisor.get() / ( nCalcCount - 1 ) ); + mfMSE = fSumErrSq.get() / nCalcCount; mfRMSE = sqrt( mfMSE ); - mfSMAPE = fSumAbsPercErr * 2.0 / nCalcCount; + mfSMAPE = fSumAbsPercErr.get() * 2.0 / nCalcCount; } /* @@ -539,7 +542,7 @@ SCSIZE ScETSForecastCalculation::CalcPeriodLen() for ( SCSIZE nPeriodLen = mnCount / 2; nPeriodLen >= 1; nPeriodLen-- ) { - double fMeanError = 0.0; + KahanSum fMeanError = 0.0; SCSIZE nPeriods = mnCount / nPeriodLen; SCSIZE nStart = mnCount - ( nPeriods * nPeriodLen ) + 1; for ( SCSIZE i = nStart; i < ( mnCount - nPeriodLen ); i++ ) @@ -547,12 +550,13 @@ SCSIZE ScETSForecastCalculation::CalcPeriodLen() fMeanError += fabs( ( maRange[ i ].Y - maRange[ i - 1 ].Y ) - ( maRange[ nPeriodLen + i ].Y - maRange[ nPeriodLen + i - 1 ].Y ) ); } - fMeanError /= static_cast< double >( ( nPeriods - 1 ) * nPeriodLen - 1 ); + double fMeanErrorGet = fMeanError.get(); + fMeanErrorGet /= static_cast< double >( ( nPeriods - 1 ) * nPeriodLen - 1 ); - if ( fMeanError <= fBestME || fMeanError == 0.0 ) + if ( fMeanErrorGet <= fBestME || fMeanErrorGet == 0.0 ) { nBestVal = nPeriodLen; - fBestME = fMeanError; + fBestME = fMeanErrorGet; } } return nBestVal; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits