sc/source/core/inc/interpre.hxx | 6 - sc/source/core/tool/interpr1.cxx | 124 ++++++++++++--------------------------- 2 files changed, 42 insertions(+), 88 deletions(-)
New commits: commit b9b744babd4d2eac73ef3684c28cfefd5b842c11 Author: dante <dante19031...@gmail.com> AuthorDate: Mon Apr 26 18:49:51 2021 +0200 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Wed Apr 28 18:09:27 2021 +0200 tdf#137679 Use Kahan summation for interpr1.cxx Includes changes for using kahan sum in ParamIfsResult. Change-Id: Iedfdd867e316d6c99146450cc3f7ac1d855b33e9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114676 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index d131b0279c2a..bdde25a12c24 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -60,8 +60,7 @@ struct CompareOptions; struct ParamIfsResult { - double mfSum = 0.0; - double mfMem = 0.0; + KahanSum mfSum = 0.0; double mfCount = 0.0; double mfMin = std::numeric_limits<double>::max(); double mfMax = std::numeric_limits<double>::lowest(); @@ -71,8 +70,7 @@ template<typename charT, typename traits> inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT, traits> & stream, const ParamIfsResult& rRes) { stream << "{" << - "sum=" << rRes.mfSum << "," << - "mem=" << rRes.mfMem << "," << + "sum=" << rRes.mfSum.get() << "," << "count=" << rRes.mfCount << "," << "min=" << rRes.mfMin << "," << "max=" << rRes.mfMax << "," << diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index f210b29049be..debe11a95581 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -3935,13 +3935,14 @@ void ScInterpreter::GetStVarParams( bool bTextAsZero, double(*VarResult)( double struct ArrayRefListValue { std::vector<double> mvValues; - double mfSum; - ArrayRefListValue() : mfSum(0.0) {} + KahanSum mfSum; + ArrayRefListValue() = default; + double get() { return mfSum.get(); } }; std::vector<ArrayRefListValue> vArrayValues; std::vector<double> values; - double fSum = 0.0; + KahanSum fSum = 0.0; double fVal = 0.0; ScAddress aAdr; ScRange aRange; @@ -3990,7 +3991,7 @@ void ScInterpreter::GetStVarParams( bool bTextAsZero, double(*VarResult)( double // Create and init all elements with current value. assert(nMatRows > 0); vArrayValues.resize(nMatRows); - for (auto & it : vArrayValues) + for (ArrayRefListValue & it : vArrayValues) { it.mvValues = values; it.mfSum = fSum; @@ -4000,7 +4001,7 @@ void ScInterpreter::GetStVarParams( bool bTextAsZero, double(*VarResult)( double { // Current value and values from vector are operands // for each vector position. - for (auto & it : vArrayValues) + for (ArrayRefListValue & it : vArrayValues) { it.mvValues.insert( it.mvValues.end(), values.begin(), values.end()); it.mfSum += fSum; @@ -4122,7 +4123,7 @@ void ScInterpreter::GetStVarParams( bool bTextAsZero, double(*VarResult)( double { ArrayRefListValue& rArrayValue = vArrayValues[r]; double vSum = 0.0; - const double vMean = rArrayValue.mfSum / n; + const double vMean = rArrayValue.get() / n; for (::std::vector<double>::size_type i = 0; i < n; i++) vSum += ::rtl::math::approxSub( rArrayValue.mvValues[i], vMean) * ::rtl::math::approxSub( rArrayValue.mvValues[i], vMean); @@ -4139,7 +4140,7 @@ void ScInterpreter::GetStVarParams( bool bTextAsZero, double(*VarResult)( double double vSum = 0.0; if (nGlobalError == FormulaError::NONE) { - const double vMean = fSum / n; + const double vMean = fSum.get() / n; for (::std::vector<double>::size_type i = 0; i < n; i++) vSum += ::rtl::math::approxSub( values[i], vMean) * ::rtl::math::approxSub( values[i], vMean); } @@ -5327,11 +5328,9 @@ void ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc ) } } - double fSum = 0.0; - double fMem = 0.0; + KahanSum fSum = 0.0; double fRes = 0.0; double fCount = 0.0; - bool bNull = true; short nParam = 1; const SCSIZE nMatRows = GetRefListArrayMaxSize( nParam); // There's either one RefList and nothing else, or none. @@ -5498,13 +5497,7 @@ void ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc ) { fVal = pSumExtraMatrix->GetDouble( nC, nR); ++fCount; - if ( bNull && fVal != 0.0 ) - { - bNull = false; - fMem = fVal; - } - else - fSum += fVal; + fSum += fVal; } } } @@ -5525,13 +5518,7 @@ void ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc ) { fVal = GetCellValue(aAdr, aCell); ++fCount; - if ( bNull && fVal != 0.0 ) - { - bNull = false; - fMem = fVal; - } - else - fSum += fVal; + fSum += fVal; } } } @@ -5555,13 +5542,7 @@ void ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc ) { fVal = pSumExtraMatrix->GetDouble( nC, nR); ++fCount; - if ( bNull && fVal != 0.0 ) - { - bNull = false; - fMem = fVal; - } - else - fSum += fVal; + fSum += fVal; } } while ( aCellIter.GetNext() ); } @@ -5576,13 +5557,7 @@ void ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc ) { fVal = GetCellValue(aAdr, aCell); ++fCount; - if ( bNull && fVal != 0.0 ) - { - bNull = false; - fMem = fVal; - } - else - fSum += fVal; + fSum += fVal; } } while ( aCellIter.GetNext() ); } @@ -5597,8 +5572,8 @@ void ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc ) switch( eFunc ) { - case ifSUMIF: fRes = ::rtl::math::approxAdd( fSum, fMem ); break; - case ifAVERAGEIF: fRes = div( ::rtl::math::approxAdd( fSum, fMem ), fCount); break; + case ifSUMIF: fRes = fSum.get(); break; + case ifAVERAGEIF: fRes = div( fSum.get(), fCount ); break; } if (xResMat) { @@ -5609,7 +5584,8 @@ void ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc ) xResMat->PutError( nGlobalError, 0, nRefListArrayPos); nGlobalError = FormulaError::NONE; } - fRes = fSum = fMem = fCount = 0.0; + fRes = fCount = 0.0; + fSum = 0; } } if (xResMat) @@ -6233,7 +6209,6 @@ void ScInterpreter::IterateParametersIfs( double(*ResultFunc)( const sc::ParamIf bool bRefArrayMain = false; while (nParam-- == nParamCount) { - bool bNull = true; SCCOL nMainCol1 = 0; SCROW nMainRow1 = 0; SCTAB nMainTab1 = 0; @@ -6387,13 +6362,7 @@ void ScInterpreter::IterateParametersIfs( double(*ResultFunc)( const sc::ParamIf continue; ++aRes.mfCount; - if (bNull && fVal != 0.0) - { - bNull = false; - aRes.mfMem = fVal; - } - else - aRes.mfSum += fVal; + aRes.mfSum += fVal; if ( aRes.mfMin > fVal ) aRes.mfMin = fVal; if ( aRes.mfMax < fVal ) @@ -6430,13 +6399,7 @@ void ScInterpreter::IterateParametersIfs( double(*ResultFunc)( const sc::ParamIf { fVal = GetCellValue(aAdr, aCell); ++aRes.mfCount; - if ( bNull && fVal != 0.0 ) - { - bNull = false; - aRes.mfMem = fVal; - } - else - aRes.mfSum += fVal; + aRes.mfSum += fVal; if ( aRes.mfMin > fVal ) aRes.mfMin = fVal; if ( aRes.mfMax < fVal ) @@ -6501,7 +6464,7 @@ void ScInterpreter::ScSumIfs() auto ResultFunc = []( const sc::ParamIfsResult& rRes ) { - return rtl::math::approxAdd(rRes.mfSum, rRes.mfMem); + return rRes.mfSum.get(); }; IterateParametersIfs(ResultFunc); } @@ -6518,7 +6481,7 @@ void ScInterpreter::ScAverageIfs() auto ResultFunc = []( const sc::ParamIfsResult& rRes ) { - return sc::div( rtl::math::approxAdd( rRes.mfSum, rRes.mfMem), rRes.mfCount); + return sc::div( rRes.mfSum.get(), rRes.mfCount); }; IterateParametersIfs(ResultFunc); } @@ -7832,8 +7795,8 @@ std::unique_ptr<ScDBQueryParamBase> ScInterpreter::GetDBParams( bool& rMissingFi void ScInterpreter::DBIterator( ScIterFunc eFunc ) { - double nErg = 0.0; - double fMem = 0.0; + double fRes = 0; + KahanSum fErg = 0; sal_uLong nCount = 0; bool bMissingField = false; unique_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) ); @@ -7850,13 +7813,12 @@ void ScInterpreter::DBIterator( ScIterFunc eFunc ) { switch( eFunc ) { - case ifPRODUCT: nErg = 1; break; - case ifMAX: nErg = -MAXDOUBLE; break; - case ifMIN: nErg = MAXDOUBLE; break; + case ifPRODUCT: fRes = 1; break; + case ifMAX: fRes = -MAXDOUBLE; break; + case ifMIN: fRes = MAXDOUBLE; break; default: ; // nothing } - bool bNull = true; do { nCount++; @@ -7864,25 +7826,19 @@ void ScInterpreter::DBIterator( ScIterFunc eFunc ) { case ifAVERAGE: case ifSUM: - if ( bNull && aValue.mfValue != 0.0 ) - { - bNull = false; - fMem = aValue.mfValue; - } - else - nErg += aValue.mfValue; + fErg += aValue.mfValue; break; case ifSUMSQ: - nErg += aValue.mfValue * aValue.mfValue; + fErg += aValue.mfValue * aValue.mfValue; break; case ifPRODUCT: - nErg *= aValue.mfValue; + fRes *= aValue.mfValue; break; case ifMAX: - if( aValue.mfValue > nErg ) nErg = aValue.mfValue; + if( aValue.mfValue > fRes ) fRes = aValue.mfValue; break; case ifMIN: - if( aValue.mfValue < nErg ) nErg = aValue.mfValue; + if( aValue.mfValue < fRes ) fRes = aValue.mfValue; break; default: ; // nothing } @@ -7895,12 +7851,13 @@ void ScInterpreter::DBIterator( ScIterFunc eFunc ) SetError( FormulaError::IllegalParameter); switch( eFunc ) { - case ifCOUNT: nErg = nCount; break; - case ifSUM: nErg = ::rtl::math::approxAdd( nErg, fMem ); break; - case ifAVERAGE: nErg = div(::rtl::math::approxAdd(nErg, fMem), nCount); break; + case ifCOUNT: fRes = nCount; break; + case ifSUM: fRes = fErg.get(); break; + case ifSUMSQ: fRes = fErg.get(); break; + case ifAVERAGE: fRes = div(fErg.get(), nCount); break; default: ; // nothing } - PushDouble( nErg ); + PushDouble( fRes ); } void ScInterpreter::ScDBSum() @@ -8019,11 +7976,10 @@ void ScInterpreter::ScDBProduct() void ScInterpreter::GetDBStVarParams( double& rVal, double& rValCount ) { std::vector<double> values; - double vSum = 0.0; - double vMean = 0.0; + KahanSum vSum = 0.0; + KahanSum fSum = 0.0; rValCount = 0.0; - double fSum = 0.0; bool bMissingField = false; unique_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) ); if (pQueryParam) @@ -8050,12 +8006,12 @@ void ScInterpreter::GetDBStVarParams( double& rVal, double& rValCount ) else SetError( FormulaError::IllegalParameter); - vMean = fSum / values.size(); + double vMean = fSum.get() / values.size(); for (double v : values) vSum += (v - vMean) * (v - vMean); - rVal = vSum; + rVal = vSum.get(); } void ScInterpreter::ScDBStdDev() _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits