[Libreoffice-commits] core.git: 3 commits - sc/source
Kohei Yoshida
kohei.yoshida at collabora.com
Fri Oct 14 22:42:29 UTC 2016
sc/source/core/inc/interpre.hxx | 21 -
sc/source/core/tool/interpr1.cxx | 749 +++++++++++++++++++--------------------
2 files changed, 395 insertions(+), 375 deletions(-)
New commits:
commit 92874f2f134d28b77163a21ff5d04c5234ca65b2
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date: Fri Oct 14 18:38:57 2016 -0400
This is no longer used.
Change-Id: I625a418c582b41ca324874e27900670151a9d2b2
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index f9e91e1..fe860eb 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -106,15 +106,6 @@ enum ScIterFuncIf
ifAVERAGEIF // Conditional average
};
-enum ScIterFuncIfs
-{
- ifSUMIFS, // Multi-Conditional sum
- ifAVERAGEIFS, // Multi-Conditional average
- ifCOUNTIFS, // Multi-Conditional count
- ifMINIFS, // Multi-Conditional minimum
- ifMAXIFS // Multi-Conditional maximum
-};
-
enum ScETSType
{
etsAdd,
commit 3bd025ec76ba305ce5892acefc57385599dd12e1
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date: Wed Oct 12 20:29:34 2016 -0400
Remove the branching at the end of IterateParametersIfs().
For (hopefully) better performance.
Change-Id: I59ed454aa9ace2f945facceee14f4e25610feebf
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 47d5afd..f9e91e1 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -39,6 +39,7 @@
#include <map>
#include <memory>
#include <vector>
+#include <limits>
class ScDocument;
class SbxVariable;
@@ -62,6 +63,15 @@ struct RangeMatrix;
struct Compare;
struct CompareOptions;
+struct ParamIfsResult
+{
+ double mfSum = 0.0;
+ double mfMem = 0.0;
+ double mfCount = 0.0;
+ double mfMin = std::numeric_limits<double>::max();
+ double mfMax = std::numeric_limits<double>::min();
+};
+
}
namespace svl {
@@ -590,7 +600,7 @@ double IterateParametersIf( ScIterFuncIf );
void ScCountIf();
void ScSumIf();
void ScAverageIf();
-double IterateParametersIfs( ScIterFuncIfs );
+void IterateParametersIfs( sc::ParamIfsResult& rRes );
void ScSumIfs();
void ScAverageIfs();
void ScCountIfs();
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 838484e..465b04b 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -5312,7 +5312,7 @@ void ScInterpreter::ScCountIf()
}
}
-double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
+void ScInterpreter::IterateParametersIfs( sc::ParamIfsResult& rRes )
{
sal_uInt8 nParamCount = GetByte();
sal_uInt8 nQueryCount = nParamCount / 2;
@@ -5321,12 +5321,6 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
size_t nRowSize = 0;
size_t nColSize = 0;
double fVal = 0.0;
- double fSum = 0.0;
- double fMem = 0.0;
- double fRes = 0.0;
- double fCount = 0.0;
- double fMin = std::numeric_limits<double>::max();
- double fMax = std::numeric_limits<double>::min();
short nParam = 1;
size_t nRefInList = 0;
SCCOL nDimensionCols = 0;
@@ -5345,7 +5339,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
{
ScAddress aAdr;
if ( !PopDoubleRefOrSingleRef( aAdr ) )
- return 0;
+ return;
ScRefCellValue aCell(*pDok, aAdr);
switch (aCell.meType)
@@ -5407,7 +5401,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
}
if (nGlobalError != FormulaError::NONE)
- return 0; // and bail out, no need to evaluate other arguments
+ return; // and bail out, no need to evaluate other arguments
// take range
nParam = 1;
@@ -5445,7 +5439,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
if (!pQueryMatrix)
{
SetError( FormulaError::IllegalParameter);
- return 0;
+ return;
}
nCol1 = 0;
nRow1 = 0;
@@ -5459,12 +5453,12 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
break;
default:
SetError( FormulaError::IllegalParameter);
- return 0;
+ return;
}
if ( nTab1 != nTab2 )
{
SetError( FormulaError::IllegalArgument);
- return 0;
+ return;
}
// All reference ranges must be of same dimension and size.
@@ -5475,12 +5469,12 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
if ((nDimensionCols != (nCol2 - nCol1 + 1)) || (nDimensionRows != (nRow2 - nRow1 + 1)))
{
SetError ( FormulaError::IllegalArgument);
- return 0;
+ return;
}
// recalculate matrix values
if (nGlobalError != FormulaError::NONE)
- return 0;
+ return;
// initialize temporary result matrix
if (aResArray.empty())
@@ -5524,7 +5518,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
if (nGlobalError != FormulaError::NONE || !pResultMatrix)
{
SetError( FormulaError::IllegalParameter);
- return 0;
+ return;
}
// result matrix is filled with boolean values.
@@ -5533,7 +5527,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
if (aResArray.size() != aResValues.size())
{
SetError( FormulaError::IllegalParameter);
- return 0;
+ return;
}
std::vector<sal_uInt8>::iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
@@ -5560,7 +5554,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
}
if (nGlobalError != FormulaError::NONE)
- return 0; // bail out
+ return; // bail out
// main range - only for AVERAGEIFS, SUMIFS, MINIFS and MAXIFS
if (nParamCount == 1)
@@ -5601,7 +5595,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
if (!pMainMatrix)
{
SetError( FormulaError::IllegalParameter);
- return 0;
+ return;
}
nMainCol1 = 0;
nMainRow1 = 0;
@@ -5615,23 +5609,23 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
break;
default:
SetError( FormulaError::IllegalParameter);
- return 0;
+ return;
}
if ( nMainTab1 != nMainTab2 )
{
SetError( FormulaError::IllegalArgument);
- return 0;
+ return;
}
// All reference ranges must be of same dimension and size.
if ((nDimensionCols != (nMainCol2 - nMainCol1 + 1)) || (nDimensionRows != (nMainRow2 - nMainRow1 + 1)))
{
SetError ( FormulaError::IllegalArgument);
- return 0;
+ return;
}
if (nGlobalError != FormulaError::NONE)
- return 0; // bail out
+ return; // bail out
// end-result calculation
ScAddress aAdr;
@@ -5643,7 +5637,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
if (aResArray.size() != aMainValues.size())
{
SetError( FormulaError::IllegalArgument);
- return 0;
+ return;
}
std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
@@ -5657,18 +5651,18 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
if (GetDoubleErrorValue(fVal) == FormulaError::ElementNaN)
continue;
- ++fCount;
+ ++rRes.mfCount;
if (bNull && fVal != 0.0)
{
bNull = false;
- fMem = fVal;
+ rRes.mfMem = fVal;
}
else
- fSum += fVal;
- if ( fMin > fVal )
- fMin = fVal;
- if ( fMax < fVal )
- fMax = fVal;
+ rRes.mfSum += fVal;
+ if ( rRes.mfMin > fVal )
+ rRes.mfMin = fVal;
+ if ( rRes.mfMax < fVal )
+ rRes.mfMax = fVal;
}
}
else
@@ -5686,18 +5680,18 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
if (aCell.hasNumeric())
{
fVal = GetCellValue(aAdr, aCell);
- ++fCount;
+ ++rRes.mfCount;
if ( bNull && fVal != 0.0 )
{
bNull = false;
- fMem = fVal;
+ rRes.mfMem = fVal;
}
else
- fSum += fVal;
- if ( fMin > fVal )
- fMin = fVal;
- if ( fMax < fVal )
- fMax = fVal;
+ rRes.mfSum += fVal;
+ if ( rRes.mfMin > fVal )
+ rRes.mfMin = fVal;
+ if ( rRes.mfMax < fVal )
+ rRes.mfMax = fVal;
}
}
}
@@ -5709,19 +5703,8 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
for (; itRes != itResEnd; ++itRes)
if (*itRes == nQueryCount)
- ++fCount;
+ ++rRes.mfCount;
}
-
- switch( eFunc )
- {
- case ifSUMIFS: fRes = ::rtl::math::approxAdd( fSum, fMem ); break;
- case ifAVERAGEIFS: fRes = div( ::rtl::math::approxAdd( fSum, fMem ), fCount); break;
- case ifCOUNTIFS: fRes = fCount; break;
- case ifMINIFS: fRes = ( fMin < std::numeric_limits<double>::max() ? fMin : 0 ); break;
- case ifMAXIFS: fRes = ( fMax > std::numeric_limits<double>::min() ? fMax : 0 ); break;
- default: ; // nothing
- }
- return fRes;
}
void ScInterpreter::ScSumIfs()
@@ -5734,7 +5717,9 @@ void ScInterpreter::ScSumIfs()
return;
}
- PushDouble( IterateParametersIfs( ifSUMIFS));
+ sc::ParamIfsResult aRes;
+ IterateParametersIfs(aRes);
+ PushDouble(rtl::math::approxAdd(aRes.mfSum, aRes.mfMem));
}
void ScInterpreter::ScAverageIfs()
@@ -5747,7 +5732,9 @@ void ScInterpreter::ScAverageIfs()
return;
}
- PushDouble( IterateParametersIfs( ifAVERAGEIFS));
+ sc::ParamIfsResult aRes;
+ IterateParametersIfs(aRes);
+ PushDouble(div(rtl::math::approxAdd(aRes.mfSum, aRes.mfMem), aRes.mfCount));
}
void ScInterpreter::ScCountIfs()
@@ -5760,7 +5747,9 @@ void ScInterpreter::ScCountIfs()
return;
}
- PushDouble( IterateParametersIfs( ifCOUNTIFS));
+ sc::ParamIfsResult aRes;
+ IterateParametersIfs(aRes);
+ PushDouble(aRes.mfCount);
}
void ScInterpreter::ScMinIfs_MS()
@@ -5773,7 +5762,9 @@ void ScInterpreter::ScMinIfs_MS()
return;
}
- PushDouble( IterateParametersIfs( ifMINIFS ) );
+ sc::ParamIfsResult aRes;
+ IterateParametersIfs(aRes);
+ PushDouble((aRes.mfMin < std::numeric_limits<double>::max()) ? aRes.mfMin : 0.0);
}
@@ -5787,7 +5778,9 @@ void ScInterpreter::ScMaxIfs_MS()
return;
}
- PushDouble( IterateParametersIfs( ifMAXIFS ) );
+ sc::ParamIfsResult aRes;
+ IterateParametersIfs(aRes);
+ PushDouble((aRes.mfMax > std::numeric_limits<double>::min()) ? aRes.mfMax : 0.0);
}
void ScInterpreter::ScLookup()
commit 19d788daff32df531d3c830dd83e198131f464db
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date: Wed Oct 12 20:29:33 2016 -0400
Do parameter count check outside of IterateParametersIfs().
To reduce branching and scoping.
Change-Id: I664e013f941c5b5dea44a6794ed133381cfc7b4c
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 51e33c7..838484e 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -5317,450 +5317,476 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
sal_uInt8 nParamCount = GetByte();
sal_uInt8 nQueryCount = nParamCount / 2;
- bool bCheck;
- if ( eFunc == ifCOUNTIFS )
- bCheck = (nParamCount >= 2) && (nParamCount % 2 == 0);
- else
- bCheck = (nParamCount >= 3) && (nParamCount % 2 == 1);
+ std::vector<sal_uInt8> aResArray;
+ size_t nRowSize = 0;
+ size_t nColSize = 0;
+ double fVal = 0.0;
+ double fSum = 0.0;
+ double fMem = 0.0;
+ double fRes = 0.0;
+ double fCount = 0.0;
+ double fMin = std::numeric_limits<double>::max();
+ double fMax = std::numeric_limits<double>::min();
+ short nParam = 1;
+ size_t nRefInList = 0;
+ SCCOL nDimensionCols = 0;
+ SCROW nDimensionRows = 0;
- if ( !bCheck )
- {
- SetError( FormulaError::ParameterExpected);
- }
- else
+ while (nParamCount > 1 && nGlobalError == FormulaError::NONE)
{
- std::vector<sal_uInt8> aResArray;
- size_t nRowSize = 0;
- size_t nColSize = 0;
- double fVal = 0.0;
- double fSum = 0.0;
- double fMem = 0.0;
- double fRes = 0.0;
- double fCount = 0.0;
- double fMin = std::numeric_limits<double>::max();
- double fMax = std::numeric_limits<double>::min();
- short nParam = 1;
- size_t nRefInList = 0;
- SCCOL nDimensionCols = 0;
- SCROW nDimensionRows = 0;
-
- while (nParamCount > 1 && nGlobalError == FormulaError::NONE)
+ // take criteria
+ svl::SharedString aString;
+ fVal = 0.0;
+ bool bIsString = true;
+ switch ( GetStackType() )
{
- // take criteria
- svl::SharedString aString;
- fVal = 0.0;
- bool bIsString = true;
- switch ( GetStackType() )
- {
- case svDoubleRef :
- case svSingleRef :
- {
- ScAddress aAdr;
- if ( !PopDoubleRefOrSingleRef( aAdr ) )
- return 0;
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ return 0;
- ScRefCellValue aCell(*pDok, aAdr);
- switch (aCell.meType)
- {
- case CELLTYPE_VALUE :
- fVal = GetCellValue(aAdr, aCell);
- bIsString = false;
- break;
- case CELLTYPE_FORMULA :
- if (aCell.mpFormula->IsValue())
- {
- fVal = GetCellValue(aAdr, aCell);
- bIsString = false;
- }
- else
- GetCellString(aString, aCell);
- break;
- case CELLTYPE_STRING :
- case CELLTYPE_EDIT :
- GetCellString(aString, aCell);
- break;
- default:
- fVal = 0.0;
- bIsString = false;
- }
- }
- break;
- case svString:
- aString = GetString();
- break;
- case svMatrix :
- case svExternalDoubleRef:
- {
- ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, aString);
- bIsString = ScMatrix::IsNonValueType( nType);
- }
- break;
- case svExternalSingleRef:
+ ScRefCellValue aCell(*pDok, aAdr);
+ switch (aCell.meType)
{
- ScExternalRefCache::TokenRef pToken;
- PopExternalSingleRef(pToken);
- if (nGlobalError == FormulaError::NONE)
- {
- if (pToken->GetType() == svDouble)
+ case CELLTYPE_VALUE :
+ fVal = GetCellValue(aAdr, aCell);
+ bIsString = false;
+ break;
+ case CELLTYPE_FORMULA :
+ if (aCell.mpFormula->IsValue())
{
- fVal = pToken->GetDouble();
+ fVal = GetCellValue(aAdr, aCell);
bIsString = false;
}
else
- aString = pToken->GetString();
- }
+ GetCellString(aString, aCell);
+ break;
+ case CELLTYPE_STRING :
+ case CELLTYPE_EDIT :
+ GetCellString(aString, aCell);
+ break;
+ default:
+ fVal = 0.0;
+ bIsString = false;
}
- break;
- default:
+ }
+ break;
+ case svString:
+ aString = GetString();
+ break;
+ case svMatrix :
+ case svExternalDoubleRef:
+ {
+ ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, aString);
+ bIsString = ScMatrix::IsNonValueType( nType);
+ }
+ break;
+ case svExternalSingleRef:
+ {
+ ScExternalRefCache::TokenRef pToken;
+ PopExternalSingleRef(pToken);
+ if (nGlobalError == FormulaError::NONE)
{
- fVal = GetDouble();
- bIsString = false;
+ if (pToken->GetType() == svDouble)
+ {
+ fVal = pToken->GetDouble();
+ bIsString = false;
+ }
+ else
+ aString = pToken->GetString();
}
- }
+ }
+ break;
+ default:
+ {
+ fVal = GetDouble();
+ bIsString = false;
+ }
+ }
- if (nGlobalError != FormulaError::NONE)
- return 0; // and bail out, no need to evaluate other arguments
+ if (nGlobalError != FormulaError::NONE)
+ return 0; // and bail out, no need to evaluate other arguments
- // take range
- nParam = 1;
- nRefInList = 0;
- SCCOL nCol1 = 0;
- SCROW nRow1 = 0;
- SCTAB nTab1 = 0;
- SCCOL nCol2 = 0;
- SCROW nRow2 = 0;
- SCTAB nTab2 = 0;
- ScMatrixRef pQueryMatrix;
- switch ( GetStackType() )
- {
- case svRefList :
- {
- ScRange aRange;
- PopDoubleRef( aRange, nParam, nRefInList);
- aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
- }
- break;
- case svDoubleRef :
- PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
- break;
- case svSingleRef :
- PopSingleRef( nCol1, nRow1, nTab1 );
- nCol2 = nCol1;
- nRow2 = nRow1;
- nTab2 = nTab1;
- break;
- case svMatrix:
- case svExternalSingleRef:
- case svExternalDoubleRef:
+ // take range
+ nParam = 1;
+ nRefInList = 0;
+ SCCOL nCol1 = 0;
+ SCROW nRow1 = 0;
+ SCTAB nTab1 = 0;
+ SCCOL nCol2 = 0;
+ SCROW nRow2 = 0;
+ SCTAB nTab2 = 0;
+ ScMatrixRef pQueryMatrix;
+ switch ( GetStackType() )
+ {
+ case svRefList :
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange, nParam, nRefInList);
+ aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ }
+ break;
+ case svDoubleRef :
+ PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ break;
+ case svSingleRef :
+ PopSingleRef( nCol1, nRow1, nTab1 );
+ nCol2 = nCol1;
+ nRow2 = nRow1;
+ nTab2 = nTab1;
+ break;
+ case svMatrix:
+ case svExternalSingleRef:
+ case svExternalDoubleRef:
+ {
+ pQueryMatrix = PopMatrix();
+ if (!pQueryMatrix)
{
- pQueryMatrix = PopMatrix();
- if (!pQueryMatrix)
- {
- SetError( FormulaError::IllegalParameter);
- return 0;
- }
- nCol1 = 0;
- nRow1 = 0;
- nTab1 = 0;
- SCSIZE nC, nR;
- pQueryMatrix->GetDimensions( nC, nR);
- nCol2 = static_cast<SCCOL>(nC - 1);
- nRow2 = static_cast<SCROW>(nR - 1);
- nTab2 = 0;
+ SetError( FormulaError::IllegalParameter);
+ return 0;
}
- break;
- default:
- SetError( FormulaError::IllegalParameter);
- return 0;
- }
- if ( nTab1 != nTab2 )
- {
- SetError( FormulaError::IllegalArgument);
+ nCol1 = 0;
+ nRow1 = 0;
+ nTab1 = 0;
+ SCSIZE nC, nR;
+ pQueryMatrix->GetDimensions( nC, nR);
+ nCol2 = static_cast<SCCOL>(nC - 1);
+ nRow2 = static_cast<SCROW>(nR - 1);
+ nTab2 = 0;
+ }
+ break;
+ default:
+ SetError( FormulaError::IllegalParameter);
return 0;
- }
+ }
+ if ( nTab1 != nTab2 )
+ {
+ SetError( FormulaError::IllegalArgument);
+ return 0;
+ }
- // All reference ranges must be of same dimension and size.
- if (!nDimensionCols)
- nDimensionCols = nCol2 - nCol1 + 1;
- if (!nDimensionRows)
- nDimensionRows = nRow2 - nRow1 + 1;
- if ((nDimensionCols != (nCol2 - nCol1 + 1)) || (nDimensionRows != (nRow2 - nRow1 + 1)))
- {
- SetError ( FormulaError::IllegalArgument);
- return 0;
- }
+ // All reference ranges must be of same dimension and size.
+ if (!nDimensionCols)
+ nDimensionCols = nCol2 - nCol1 + 1;
+ if (!nDimensionRows)
+ nDimensionRows = nRow2 - nRow1 + 1;
+ if ((nDimensionCols != (nCol2 - nCol1 + 1)) || (nDimensionRows != (nRow2 - nRow1 + 1)))
+ {
+ SetError ( FormulaError::IllegalArgument);
+ return 0;
+ }
- // recalculate matrix values
- if (nGlobalError != FormulaError::NONE)
- return 0;
+ // recalculate matrix values
+ if (nGlobalError != FormulaError::NONE)
+ return 0;
- // initialize temporary result matrix
- if (aResArray.empty())
- {
- nColSize = nCol2 - nCol1 + 1;
- nRowSize = nRow2 - nRow1 + 1;
- aResArray.resize(nColSize*nRowSize, 0);
- }
+ // initialize temporary result matrix
+ if (aResArray.empty())
+ {
+ nColSize = nCol2 - nCol1 + 1;
+ nRowSize = nRow2 - nRow1 + 1;
+ aResArray.resize(nColSize*nRowSize, 0);
+ }
- ScQueryParam rParam;
- rParam.nRow1 = nRow1;
- rParam.nRow2 = nRow2;
+ ScQueryParam rParam;
+ rParam.nRow1 = nRow1;
+ rParam.nRow2 = nRow2;
- ScQueryEntry& rEntry = rParam.GetEntry(0);
- ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
- rEntry.bDoQuery = true;
- if (!bIsString)
+ ScQueryEntry& rEntry = rParam.GetEntry(0);
+ ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
+ rEntry.bDoQuery = true;
+ if (!bIsString)
+ {
+ rItem.meType = ScQueryEntry::ByValue;
+ rItem.mfVal = fVal;
+ rEntry.eOp = SC_EQUAL;
+ }
+ else
+ {
+ rParam.FillInExcelSyntax(pDok->GetSharedStringPool(), aString.getString(), 0, pFormatter);
+ if (rItem.meType == ScQueryEntry::ByString)
+ rParam.eSearchType = DetectSearchType(rItem.maString.getString(), pDok);
+ }
+ ScAddress aAdr;
+ aAdr.SetTab( nTab1 );
+ rParam.nCol1 = nCol1;
+ rParam.nCol2 = nCol2;
+ rEntry.nField = nCol1;
+ SCsCOL nColDiff = -nCol1;
+ SCsROW nRowDiff = -nRow1;
+ if (pQueryMatrix)
+ {
+ // Never case-sensitive.
+ sc::CompareOptions aOptions( pDok, rEntry, rParam.eSearchType);
+ ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
+ if (nGlobalError != FormulaError::NONE || !pResultMatrix)
{
- rItem.meType = ScQueryEntry::ByValue;
- rItem.mfVal = fVal;
- rEntry.eOp = SC_EQUAL;
+ SetError( FormulaError::IllegalParameter);
+ return 0;
}
- else
+
+ // result matrix is filled with boolean values.
+ std::vector<double> aResValues;
+ pResultMatrix->GetDoubleArray(aResValues);
+ if (aResArray.size() != aResValues.size())
{
- rParam.FillInExcelSyntax(pDok->GetSharedStringPool(), aString.getString(), 0, pFormatter);
- if (rItem.meType == ScQueryEntry::ByString)
- rParam.eSearchType = DetectSearchType(rItem.maString.getString(), pDok);
+ SetError( FormulaError::IllegalParameter);
+ return 0;
}
- ScAddress aAdr;
- aAdr.SetTab( nTab1 );
- rParam.nCol1 = nCol1;
- rParam.nCol2 = nCol2;
- rEntry.nField = nCol1;
- SCsCOL nColDiff = -nCol1;
- SCsROW nRowDiff = -nRow1;
- if (pQueryMatrix)
+
+ std::vector<sal_uInt8>::iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
+ std::vector<double>::const_iterator itThisRes = aResValues.begin();
+ for (; itRes != itResEnd; ++itRes, ++itThisRes)
+ *itRes += *itThisRes;
+ }
+ else
+ {
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false);
+ // Increment Entry.nField in iterator when switching to next column.
+ aCellIter.SetAdvanceQueryParamEntryField( true );
+ if ( aCellIter.GetFirst() )
{
- // Never case-sensitive.
- sc::CompareOptions aOptions( pDok, rEntry, rParam.eSearchType);
- ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
- if (nGlobalError != FormulaError::NONE || !pResultMatrix)
+ do
{
- SetError( FormulaError::IllegalParameter);
- return 0;
- }
+ size_t nC = aCellIter.GetCol() + nColDiff;
+ size_t nR = aCellIter.GetRow() + nRowDiff;
+ ++aResArray[nC*nRowSize+nR];
+ } while ( aCellIter.GetNext() );
+ }
+ }
+ nParamCount -= 2;
+ }
- // result matrix is filled with boolean values.
- std::vector<double> aResValues;
- pResultMatrix->GetDoubleArray(aResValues);
- if (aResArray.size() != aResValues.size())
+ if (nGlobalError != FormulaError::NONE)
+ return 0; // bail out
+
+ // main range - only for AVERAGEIFS, SUMIFS, MINIFS and MAXIFS
+ if (nParamCount == 1)
+ {
+ nParam = 1;
+ nRefInList = 0;
+ bool bNull = true;
+ SCCOL nMainCol1 = 0;
+ SCROW nMainRow1 = 0;
+ SCTAB nMainTab1 = 0;
+ SCCOL nMainCol2 = 0;
+ SCROW nMainRow2 = 0;
+ SCTAB nMainTab2 = 0;
+ ScMatrixRef pMainMatrix;
+ switch ( GetStackType() )
+ {
+ case svRefList :
{
- SetError( FormulaError::IllegalParameter);
- return 0;
+ ScRange aRange;
+ PopDoubleRef( aRange, nParam, nRefInList);
+ aRange.GetVars( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2);
}
-
- std::vector<sal_uInt8>::iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
- std::vector<double>::const_iterator itThisRes = aResValues.begin();
- for (; itRes != itResEnd; ++itRes, ++itThisRes)
- *itRes += *itThisRes;
- }
- else
- {
- ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false);
- // Increment Entry.nField in iterator when switching to next column.
- aCellIter.SetAdvanceQueryParamEntryField( true );
- if ( aCellIter.GetFirst() )
+ break;
+ case svDoubleRef :
+ PopDoubleRef( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2 );
+ break;
+ case svSingleRef :
+ PopSingleRef( nMainCol1, nMainRow1, nMainTab1 );
+ nMainCol2 = nMainCol1;
+ nMainRow2 = nMainRow1;
+ nMainTab2 = nMainTab1;
+ break;
+ case svMatrix:
+ case svExternalSingleRef:
+ case svExternalDoubleRef:
{
- do
+ pMainMatrix = PopMatrix();
+ if (!pMainMatrix)
{
- size_t nC = aCellIter.GetCol() + nColDiff;
- size_t nR = aCellIter.GetRow() + nRowDiff;
- ++aResArray[nC*nRowSize+nR];
- } while ( aCellIter.GetNext() );
+ SetError( FormulaError::IllegalParameter);
+ return 0;
+ }
+ nMainCol1 = 0;
+ nMainRow1 = 0;
+ nMainTab1 = 0;
+ SCSIZE nC, nR;
+ pMainMatrix->GetDimensions( nC, nR);
+ nMainCol2 = static_cast<SCCOL>(nC - 1);
+ nMainRow2 = static_cast<SCROW>(nR - 1);
+ nMainTab2 = 0;
}
- }
- nParamCount -= 2;
+ break;
+ default:
+ SetError( FormulaError::IllegalParameter);
+ return 0;
+ }
+ if ( nMainTab1 != nMainTab2 )
+ {
+ SetError( FormulaError::IllegalArgument);
+ return 0;
+ }
+
+ // All reference ranges must be of same dimension and size.
+ if ((nDimensionCols != (nMainCol2 - nMainCol1 + 1)) || (nDimensionRows != (nMainRow2 - nMainRow1 + 1)))
+ {
+ SetError ( FormulaError::IllegalArgument);
+ return 0;
}
if (nGlobalError != FormulaError::NONE)
return 0; // bail out
- // main range - only for AVERAGEIFS, SUMIFS, MINIFS and MAXIFS
- if (nParamCount == 1)
+ // end-result calculation
+ ScAddress aAdr;
+ aAdr.SetTab( nMainTab1 );
+ if (pMainMatrix)
{
- nParam = 1;
- nRefInList = 0;
- bool bNull = true;
- SCCOL nMainCol1 = 0;
- SCROW nMainRow1 = 0;
- SCTAB nMainTab1 = 0;
- SCCOL nMainCol2 = 0;
- SCROW nMainRow2 = 0;
- SCTAB nMainTab2 = 0;
- ScMatrixRef pMainMatrix;
- switch ( GetStackType() )
- {
- case svRefList :
- {
- ScRange aRange;
- PopDoubleRef( aRange, nParam, nRefInList);
- aRange.GetVars( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2);
- }
- break;
- case svDoubleRef :
- PopDoubleRef( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2 );
- break;
- case svSingleRef :
- PopSingleRef( nMainCol1, nMainRow1, nMainTab1 );
- nMainCol2 = nMainCol1;
- nMainRow2 = nMainRow1;
- nMainTab2 = nMainTab1;
- break;
- case svMatrix:
- case svExternalSingleRef:
- case svExternalDoubleRef:
- {
- pMainMatrix = PopMatrix();
- if (!pMainMatrix)
- {
- SetError( FormulaError::IllegalParameter);
- return 0;
- }
- nMainCol1 = 0;
- nMainRow1 = 0;
- nMainTab1 = 0;
- SCSIZE nC, nR;
- pMainMatrix->GetDimensions( nC, nR);
- nMainCol2 = static_cast<SCCOL>(nC - 1);
- nMainRow2 = static_cast<SCROW>(nR - 1);
- nMainTab2 = 0;
- }
- break;
- default:
- SetError( FormulaError::IllegalParameter);
- return 0;
- }
- if ( nMainTab1 != nMainTab2 )
+ std::vector<double> aMainValues;
+ pMainMatrix->GetDoubleArray(aMainValues, false); // Map empty values to NaN's.
+ if (aResArray.size() != aMainValues.size())
{
SetError( FormulaError::IllegalArgument);
return 0;
}
- // All reference ranges must be of same dimension and size.
- if ((nDimensionCols != (nMainCol2 - nMainCol1 + 1)) || (nDimensionRows != (nMainRow2 - nMainRow1 + 1)))
+ std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
+ std::vector<double>::const_iterator itMain = aMainValues.begin();
+ for (; itRes != itResEnd; ++itRes, ++itMain)
{
- SetError ( FormulaError::IllegalArgument);
- return 0;
- }
-
- if (nGlobalError != FormulaError::NONE)
- return 0; // bail out
+ if (*itRes != nQueryCount)
+ continue;
- // end-result calculation
- ScAddress aAdr;
- aAdr.SetTab( nMainTab1 );
- if (pMainMatrix)
- {
- std::vector<double> aMainValues;
- pMainMatrix->GetDoubleArray(aMainValues, false); // Map empty values to NaN's.
- if (aResArray.size() != aMainValues.size())
- {
- SetError( FormulaError::IllegalArgument);
- return 0;
- }
+ fVal = *itMain;
+ if (GetDoubleErrorValue(fVal) == FormulaError::ElementNaN)
+ continue;
- std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
- std::vector<double>::const_iterator itMain = aMainValues.begin();
- for (; itRes != itResEnd; ++itRes, ++itMain)
+ ++fCount;
+ if (bNull && fVal != 0.0)
{
- if (*itRes != nQueryCount)
- continue;
-
- fVal = *itMain;
- if (GetDoubleErrorValue(fVal) == FormulaError::ElementNaN)
- continue;
-
- ++fCount;
- if (bNull && fVal != 0.0)
- {
- bNull = false;
- fMem = fVal;
- }
- else
- fSum += fVal;
- if ( fMin > fVal )
- fMin = fVal;
- if ( fMax < fVal )
- fMax = fVal;
+ bNull = false;
+ fMem = fVal;
}
+ else
+ fSum += fVal;
+ if ( fMin > fVal )
+ fMin = fVal;
+ if ( fMax < fVal )
+ fMax = fVal;
}
- else
+ }
+ else
+ {
+ std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin();
+ for (size_t nCol = 0; nCol < nColSize; ++nCol)
{
- std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin();
- for (size_t nCol = 0; nCol < nColSize; ++nCol)
+ for (size_t nRow = 0; nRow < nRowSize; ++nRow, ++itRes)
{
- for (size_t nRow = 0; nRow < nRowSize; ++nRow, ++itRes)
+ if (*itRes == nQueryCount)
{
- if (*itRes == nQueryCount)
+ aAdr.SetCol( static_cast<SCCOL>(nCol) + nMainCol1);
+ aAdr.SetRow( static_cast<SCROW>(nRow) + nMainRow1);
+ ScRefCellValue aCell(*pDok, aAdr);
+ if (aCell.hasNumeric())
{
- aAdr.SetCol( static_cast<SCCOL>(nCol) + nMainCol1);
- aAdr.SetRow( static_cast<SCROW>(nRow) + nMainRow1);
- ScRefCellValue aCell(*pDok, aAdr);
- if (aCell.hasNumeric())
+ fVal = GetCellValue(aAdr, aCell);
+ ++fCount;
+ if ( bNull && fVal != 0.0 )
{
- fVal = GetCellValue(aAdr, aCell);
- ++fCount;
- if ( bNull && fVal != 0.0 )
- {
- bNull = false;
- fMem = fVal;
- }
- else
- fSum += fVal;
- if ( fMin > fVal )
- fMin = fVal;
- if ( fMax < fVal )
- fMax = fVal;
+ bNull = false;
+ fMem = fVal;
}
+ else
+ fSum += fVal;
+ if ( fMin > fVal )
+ fMin = fVal;
+ if ( fMax < fVal )
+ fMax = fVal;
}
}
}
}
}
- else
- {
- std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
- for (; itRes != itResEnd; ++itRes)
- if (*itRes == nQueryCount)
- ++fCount;
- }
+ }
+ else
+ {
+ std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
+ for (; itRes != itResEnd; ++itRes)
+ if (*itRes == nQueryCount)
+ ++fCount;
+ }
- switch( eFunc )
- {
- case ifSUMIFS: fRes = ::rtl::math::approxAdd( fSum, fMem ); break;
- case ifAVERAGEIFS: fRes = div( ::rtl::math::approxAdd( fSum, fMem ), fCount); break;
- case ifCOUNTIFS: fRes = fCount; break;
- case ifMINIFS: fRes = ( fMin < std::numeric_limits<double>::max() ? fMin : 0 ); break;
- case ifMAXIFS: fRes = ( fMax > std::numeric_limits<double>::min() ? fMax : 0 ); break;
- default: ; // nothing
- }
- return fRes;
+ switch( eFunc )
+ {
+ case ifSUMIFS: fRes = ::rtl::math::approxAdd( fSum, fMem ); break;
+ case ifAVERAGEIFS: fRes = div( ::rtl::math::approxAdd( fSum, fMem ), fCount); break;
+ case ifCOUNTIFS: fRes = fCount; break;
+ case ifMINIFS: fRes = ( fMin < std::numeric_limits<double>::max() ? fMin : 0 ); break;
+ case ifMAXIFS: fRes = ( fMax > std::numeric_limits<double>::min() ? fMax : 0 ); break;
+ default: ; // nothing
}
- return 0;
+ return fRes;
}
void ScInterpreter::ScSumIfs()
{
+ sal_uInt8 nParamCount = GetByte();
+
+ if (nParamCount < 3 || (nParamCount % 2 != 1))
+ {
+ SetError( FormulaError::ParameterExpected);
+ return;
+ }
+
PushDouble( IterateParametersIfs( ifSUMIFS));
}
void ScInterpreter::ScAverageIfs()
{
+ sal_uInt8 nParamCount = GetByte();
+
+ if (nParamCount < 3 || (nParamCount % 2 != 1))
+ {
+ SetError( FormulaError::ParameterExpected);
+ return;
+ }
+
PushDouble( IterateParametersIfs( ifAVERAGEIFS));
}
void ScInterpreter::ScCountIfs()
{
+ sal_uInt8 nParamCount = GetByte();
+
+ if (nParamCount < 2 || (nParamCount % 2 != 0))
+ {
+ SetError( FormulaError::ParameterExpected);
+ return;
+ }
+
PushDouble( IterateParametersIfs( ifCOUNTIFS));
}
void ScInterpreter::ScMinIfs_MS()
{
+ sal_uInt8 nParamCount = GetByte();
+
+ if (nParamCount < 3 || (nParamCount % 2 != 1))
+ {
+ SetError( FormulaError::ParameterExpected);
+ return;
+ }
+
PushDouble( IterateParametersIfs( ifMINIFS ) );
}
void ScInterpreter::ScMaxIfs_MS()
{
+ sal_uInt8 nParamCount = GetByte();
+
+ if (nParamCount < 3 || (nParamCount % 2 != 1))
+ {
+ SetError( FormulaError::ParameterExpected);
+ return;
+ }
+
PushDouble( IterateParametersIfs( ifMAXIFS ) );
}
More information about the Libreoffice-commits
mailing list