Kaydet (Commit) 77ca13a2 authored tarafından Eike Rathke's avatar Eike Rathke

Use ScFunctionData and thus Welford in Consolidation

Change-Id: I83972b07dafadf87f7322897332bbdf0cf58afd3
Reviewed-on: https://gerrit.libreoffice.org/65162Reviewed-by: 's avatarEike Rathke <erack@redhat.com>
Tested-by: Jenkins
üst 98e84dc5
......@@ -25,6 +25,7 @@
#include <vector>
class ScDocument;
class ScFunctionData;
// Sequence:
// 1) create ScConsData
......@@ -54,9 +55,7 @@ private:
SCSIZE nColCount;
SCSIZE nRowCount;
std::unique_ptr<std::unique_ptr<bool[]>[]> ppUsed;
std::unique_ptr<std::unique_ptr<double[]>[]> ppSum;
std::unique_ptr<std::unique_ptr<double[]>[]> ppCount;
std::unique_ptr<std::unique_ptr<double[]>[]> ppSumSqr;
std::unique_ptr<std::unique_ptr<ScFunctionData[]>[]> ppFunctionData;
std::unique_ptr<std::unique_ptr<ScReferenceList[]>[]> ppRefs;
::std::vector<OUString> maColHeaders;
::std::vector<OUString> maRowHeaders;
......
......@@ -62,21 +62,23 @@ private:
class ScFunctionData
{
public:
ScFunctionData() : meFunc(SUBTOTAL_FUNC_NONE), mbError(false) {}
ScFunctionData( ScSubTotalFunc eFn ) : meFunc(eFn), mbError(false) {}
void update( double fNewVal );
void update( double fNewVal );
/// Check getError() after (!) obtaining the result.
double getResult();
bool getError() const { return mbError; }
ScSubTotalFunc getFunc() const { return meFunc; }
void setError() { mbError = true; }
double getResult();
bool getError() const { return mbError; }
ScSubTotalFunc getFunc() const { return meFunc; }
void setError() { mbError = true; }
private:
WelfordRunner maWelford;
ScSubTotalFunc const meFunc;
bool mbError;
WelfordRunner maWelford;
ScSubTotalFunc meFunc;
bool mbError;
double& getValueRef() { return maWelford.mfMean; }
sal_uInt64& getCountRef() { return maWelford.mnCount; }
double& getValueRef() { return maWelford.mfMean; }
sal_uInt64& getCountRef() { return maWelford.mnCount; }
};
#endif
......
......@@ -73,9 +73,7 @@ ScConsData::~ScConsData()
void ScConsData::DeleteData()
{
ppRefs.reset();
ppCount.reset();
ppSum.reset();
ppSumSqr.reset();
ppFunctionData.reset();
ppUsed.reset();
ppTitlePos.reset();
::std::vector<OUString>().swap( maColHeaders);
......@@ -98,16 +96,12 @@ void ScConsData::InitData()
for (SCSIZE i=0; i<nColCount; i++)
ppRefs[i].reset(new ScReferenceList[nRowCount]);
}
else if (nColCount && !ppCount)
else if (nColCount && !ppFunctionData)
{
ppCount.reset( new std::unique_ptr<double[]>[nColCount] );
ppSum.reset( new std::unique_ptr<double[]>[nColCount] );
ppSumSqr.reset( new std::unique_ptr<double[]>[nColCount] );
ppFunctionData.reset( new std::unique_ptr<ScFunctionData[]>[nColCount] );
for (SCSIZE i=0; i<nColCount; i++)
{
ppCount[i].reset( new double[nRowCount] );
ppSum[i].reset( new double[nRowCount] );
ppSumSqr[i].reset( new double[nRowCount] );
ppFunctionData[i].reset( new ScFunctionData[nRowCount] );
}
}
......@@ -243,158 +237,6 @@ void ScConsData::AddName( const OUString& rName )
}
}
// rCount < 0 <=> error
static void lcl_UpdateArray( ScSubTotalFunc eFunc,
double& rCount, double& rSum, double& rSumSqr, double nVal )
{
if (rCount < 0.0)
return;
switch (eFunc)
{
case SUBTOTAL_FUNC_SUM:
if (!SubTotal::SafePlus(rSum, nVal))
rCount = -MAXDOUBLE;
break;
case SUBTOTAL_FUNC_PROD:
if (!SubTotal::SafeMult(rSum, nVal))
rCount = -MAXDOUBLE;
break;
case SUBTOTAL_FUNC_CNT:
case SUBTOTAL_FUNC_CNT2:
rCount += 1.0;
break;
case SUBTOTAL_FUNC_AVE:
if (!SubTotal::SafePlus(rSum, nVal))
rCount = -MAXDOUBLE;
else
rCount += 1.0;
break;
case SUBTOTAL_FUNC_MAX:
if (nVal > rSum)
rSum = nVal;
break;
case SUBTOTAL_FUNC_MIN:
if (nVal < rSum)
rSum = nVal;
break;
case SUBTOTAL_FUNC_STD:
case SUBTOTAL_FUNC_STDP:
case SUBTOTAL_FUNC_VAR:
case SUBTOTAL_FUNC_VARP:
{
bool bOk = SubTotal::SafePlus(rSum, nVal);
bOk = bOk && SubTotal::SafeMult(nVal, nVal);
bOk = bOk && SubTotal::SafePlus(rSumSqr, nVal);
if (!bOk)
rCount = -MAXDOUBLE;
else
rCount += 1.0;
break;
}
default:
{
// added to avoid warnings
}
}
}
static void lcl_InitArray( ScSubTotalFunc eFunc,
double& rCount, double& rSum, double& rSumSqr, double nVal )
{
rCount = 1.0;
switch (eFunc)
{
case SUBTOTAL_FUNC_SUM:
case SUBTOTAL_FUNC_MAX:
case SUBTOTAL_FUNC_MIN:
case SUBTOTAL_FUNC_PROD:
case SUBTOTAL_FUNC_AVE:
rSum = nVal;
break;
case SUBTOTAL_FUNC_STD:
case SUBTOTAL_FUNC_STDP:
case SUBTOTAL_FUNC_VAR:
case SUBTOTAL_FUNC_VARP:
{
rSum = nVal;
bool bOk = SubTotal::SafeMult(nVal, nVal);
if (bOk)
rSumSqr = nVal;
else
rCount = -MAXDOUBLE;
}
break;
default:
break;
}
}
static double lcl_CalcData( ScSubTotalFunc eFunc,
double& fCount, double fSum, double fSumSqr)
{
if (fCount < 0.0)
return 0.0;
double fVal = 0.0;
switch (eFunc)
{
case SUBTOTAL_FUNC_CNT:
case SUBTOTAL_FUNC_CNT2:
fVal = fCount;
break;
case SUBTOTAL_FUNC_SUM:
case SUBTOTAL_FUNC_MAX:
case SUBTOTAL_FUNC_MIN:
case SUBTOTAL_FUNC_PROD:
fVal = fSum;
break;
case SUBTOTAL_FUNC_AVE:
if (fCount > 0.0)
fVal = fSum / fCount;
else
fCount = -MAXDOUBLE;
break;
case SUBTOTAL_FUNC_STD:
{
if (fCount > 1 && SubTotal::SafeMult(fSum, fSum))
fVal = sqrt((fSumSqr - fSum/fCount)/(fCount-1.0));
else
fCount = -MAXDOUBLE;
}
break;
case SUBTOTAL_FUNC_STDP:
{
if (fCount > 0 && SubTotal::SafeMult(fSum, fSum))
fVal = sqrt((fSumSqr - fSum/fCount)/fCount);
else
fCount = -MAXDOUBLE;
}
break;
case SUBTOTAL_FUNC_VAR:
{
if (fCount > 1 && SubTotal::SafeMult(fSum, fSum))
fVal = (fSumSqr - fSum/fCount)/(fCount-1.0);
else
fCount = -MAXDOUBLE;
}
break;
case SUBTOTAL_FUNC_VARP:
{
if (fCount > 0 && SubTotal::SafeMult(fSum, fSum))
fVal = (fSumSqr - fSum/fCount)/fCount;
else
fCount = -MAXDOUBLE;
}
break;
default:
{
OSL_FAIL("Consoli::CalcData: unknown function");
fCount = -MAXDOUBLE;
}
break;
}
return fVal;
}
void ScConsData::AddData( ScDocument* pSrcDoc, SCTAB nTab,
SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
{
......@@ -511,17 +353,12 @@ void ScConsData::AddData( ScDocument* pSrcDoc, SCTAB nTab,
{
double nVal;
pSrcDoc->GetValue( nCol, nRow, nTab, nVal );
if (ppUsed[nArrX][nArrY])
lcl_UpdateArray( eFunction, ppCount[nArrX][nArrY],
ppSum[nArrX][nArrY], ppSumSqr[nArrX][nArrY],
nVal);
else
if (!ppUsed[nArrX][nArrY])
{
ppUsed[nArrX][nArrY] = true;
lcl_InitArray( eFunction, ppCount[nArrX][nArrY],
ppSum[nArrX][nArrY],
ppSumSqr[nArrX][nArrY], nVal );
ppFunctionData[nArrX][nArrY] = ScFunctionData( eFunction);
}
ppFunctionData[nArrX][nArrY].update( nVal);
}
}
}
......@@ -584,16 +421,14 @@ void ScConsData::OutputToDocument( ScDocument* pDestDoc, SCCOL nCol, SCROW nRow,
// data
if ( ppCount && ppUsed ) // insert values directly
if ( ppFunctionData && ppUsed ) // insert values directly
{
for (nArrX=0; nArrX<nColCount; nArrX++)
for (nArrY=0; nArrY<nRowCount; nArrY++)
if (ppUsed[nArrX][nArrY])
{
double fVal = lcl_CalcData( eFunction, ppCount[nArrX][nArrY],
ppSum[nArrX][nArrY],
ppSumSqr[nArrX][nArrY]);
if (ppCount[nArrX][nArrY] < 0.0)
double fVal = ppFunctionData[nArrX][nArrY].getResult();
if (ppFunctionData[nArrX][nArrY].getError())
pDestDoc->SetError( sal::static_int_cast<SCCOL>(nCol+nArrX),
sal::static_int_cast<SCROW>(nRow+nArrY), nTab, FormulaError::NoValue );
else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment