[Libreoffice-commits] core.git: sc/source
dante (via logerrit)
logerrit at kemper.freedesktop.org
Wed Apr 28 16:10:09 UTC 2021
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 <dante19031999 at gmail.com>
AuthorDate: Mon Apr 26 18:49:51 2021 +0200
Commit: Mike Kaganski <mike.kaganski at 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.kaganski at 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()
More information about the Libreoffice-commits
mailing list