summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sc/source/core/tool/interpr3.cxx59
1 files changed, 33 insertions, 26 deletions
diff --git a/sc/source/core/tool/interpr3.cxx b/sc/source/core/tool/interpr3.cxx
index c545d781911b..3e41643e6c50 100644
--- a/sc/source/core/tool/interpr3.cxx
+++ b/sc/source/core/tool/interpr3.cxx
@@ -3642,48 +3642,50 @@ void ScInterpreter::CalculateSmallLarge(bool bSmall)
SCSIZE nCol = 0, nRow = 0;
auto aArray = GetTopNumberArray(nCol, nRow);
- auto aArraySize = aArray.size();
- if (aArraySize == 0 || nGlobalError != FormulaError::NONE)
+ const auto nRankArraySize = aArray.size();
+ if (nRankArraySize == 0 || nGlobalError != FormulaError::NONE)
{
PushNoValue();
return;
}
- assert(aArraySize == nCol * nRow);
- for (double fArg : aArray)
- {
- double f = ::rtl::math::approxFloor(fArg);
- if (f < 1.0)
- {
- PushIllegalArgument();
- return;
- }
- }
+ assert(nRankArraySize == nCol * nRow);
std::vector<SCSIZE> aRankArray;
- aRankArray.reserve(aArraySize);
+ aRankArray.reserve(nRankArraySize);
std::transform(aArray.begin(), aArray.end(), std::back_inserter(aRankArray),
- [](double f) { return static_cast<SCSIZE>(f); });
-
- auto itMaxRank = std::max_element(aRankArray.begin(), aRankArray.end());
- assert(itMaxRank != aRankArray.end());
- SCSIZE k = *itMaxRank;
+ [](double f) {
+ f = rtl::math::approxFloor(f);
+ // Valid ranks are >= 1.
+ if (f < 1.0 || f > std::numeric_limits<SCSIZE>::max())
+ return static_cast<SCSIZE>(0);
+ return static_cast<SCSIZE>(f);
+ });
vector<double> aSortArray;
GetNumberSequenceArray(1, aSortArray, false );
- SCSIZE nSize = aSortArray.size();
- if (nSize == 0 || nGlobalError != FormulaError::NONE || nSize < k)
+ const SCSIZE nSize = aSortArray.size();
+ if (nSize == 0 || nGlobalError != FormulaError::NONE)
PushNoValue();
- else if (aArraySize == 1)
+ else if (nRankArraySize == 1)
{
- vector<double>::iterator iPos = aSortArray.begin() + (bSmall ? k-1 : nSize-k);
- ::std::nth_element( aSortArray.begin(), iPos, aSortArray.end());
- PushDouble( *iPos);
+ const SCSIZE k = aRankArray[0];
+ if (k < 1 || nSize < k)
+ PushNoValue();
+ else
+ {
+ vector<double>::iterator iPos = aSortArray.begin() + (bSmall ? k-1 : nSize-k);
+ ::std::nth_element( aSortArray.begin(), iPos, aSortArray.end());
+ PushDouble( *iPos);
+ }
}
else
{
std::set<SCSIZE> aIndices;
for (SCSIZE n : aRankArray)
- aIndices.insert(bSmall ? n-1 : nSize-n);
+ {
+ if (1 <= n && n <= nSize)
+ aIndices.insert(bSmall ? n-1 : nSize-n);
+ }
// We can spare sorting when the total number of ranks is small enough.
// Find only the elements at given indices if, arbitrarily, the index size is
// smaller than 1/3 of the haystack array's size; just sort it squarely, otherwise.
@@ -3702,7 +3704,12 @@ void ScInterpreter::CalculateSmallLarge(bool bSmall)
aArray.clear();
for (SCSIZE n : aRankArray)
- aArray.push_back(aSortArray[bSmall ? n-1 : nSize-n]);
+ {
+ if (1 <= n && n <= nSize)
+ aArray.push_back( aSortArray[bSmall ? n-1 : nSize-n]);
+ else
+ aArray.push_back( CreateDoubleError( FormulaError::NoValue));
+ }
ScMatrixRef pResult = GetNewMat(nCol, nRow, aArray);
PushMatrix(pResult);
}