summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2023-03-03 13:39:03 +0100
committerEike Rathke <erack@redhat.com>2023-03-04 00:36:13 +0000
commit019e751c71dcb2d34c6fd8bb9dda267c6ba2b48e (patch)
tree3da89559d8ad485cd0bb9456880293c5625dc163
parentdb5b7400aec082dacdc09f8b741c70aa5852f25c (diff)
Resolves: tdf#153924 handle non-numeric and error values in rank array
... of LARGE()/SMALL() instead of yielding error value for all result elements. Fallout from commit e4c2d0bb57ab8ea8f5c400d103d01376b8140f22 CommitDate: Fri Nov 30 22:14:17 2018 +0100 i#32345 Support a matrix of rank argument for LARGE()/SMALL() that in ScInterpreter::GetTopNumberArray() required the entire rank array would have to be numeric, which with an empty cell or string it isn't. Change-Id: Ieaa1a68bb8f98614119550b1442665b6fbb4817a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148178 Reviewed-by: Eike Rathke <erack@redhat.com> Tested-by: Jenkins
-rw-r--r--sc/source/core/tool/interpr3.cxx44
1 files changed, 32 insertions, 12 deletions
diff --git a/sc/source/core/tool/interpr3.cxx b/sc/source/core/tool/interpr3.cxx
index d95510acd51c..c20d7e0327e1 100644
--- a/sc/source/core/tool/interpr3.cxx
+++ b/sc/source/core/tool/interpr3.cxx
@@ -3638,8 +3638,8 @@ void ScInterpreter::CalculateSmallLarge(bool bSmall)
return;
SCSIZE nCol = 0, nRow = 0;
- auto aArray = GetTopNumberArray(nCol, nRow);
- const auto nRankArraySize = aArray.size();
+ const auto aArray = GetTopNumberArray(nCol, nRow);
+ const size_t nRankArraySize = aArray.size();
if (nRankArraySize == 0 || nGlobalError != FormulaError::NONE)
{
PushNoValue();
@@ -3667,7 +3667,12 @@ void ScInterpreter::CalculateSmallLarge(bool bSmall)
{
const SCSIZE k = aRankArray[0];
if (k < 1 || nSize < k)
- PushNoValue();
+ {
+ if (!std::isfinite(aArray[0]))
+ PushDouble(aArray[0]); // propagates error
+ else
+ PushNoValue();
+ }
else
{
vector<double>::iterator iPos = aSortArray.begin() + (bSmall ? k-1 : nSize-k);
@@ -3699,15 +3704,19 @@ void ScInterpreter::CalculateSmallLarge(bool bSmall)
else
std::sort(aSortArray.begin(), aSortArray.end());
- aArray.clear();
- for (SCSIZE n : aRankArray)
+ std::vector<double> aResultArray;
+ aResultArray.reserve(nRankArraySize);
+ for (size_t i = 0; i < nRankArraySize; ++i)
{
+ const SCSIZE n = aRankArray[i];
if (1 <= n && n <= nSize)
- aArray.push_back( aSortArray[bSmall ? n-1 : nSize-n]);
+ aResultArray.push_back( aSortArray[bSmall ? n-1 : nSize-n]);
+ else if (!std::isfinite( aArray[i]))
+ aResultArray.push_back( aArray[i]); // propagate error
else
- aArray.push_back( CreateDoubleError( FormulaError::NoValue));
+ aResultArray.push_back( CreateDoubleError( FormulaError::IllegalArgument));
}
- ScMatrixRef pResult = GetNewMat(nCol, nRow, aArray);
+ ScMatrixRef pResult = GetNewMat(nCol, nRow, aResultArray);
PushMatrix(pResult);
}
}
@@ -3912,19 +3921,30 @@ std::vector<double> ScInterpreter::GetTopNumberArray( SCSIZE& rCol, SCSIZE& rRow
if (!pMat)
break;
+ const SCSIZE nCount = pMat->GetElementCount();
+ aArray.reserve(nCount);
+ // Do not propagate errors from matrix elements as global error.
+ pMat->SetErrorInterpreter(nullptr);
if (pMat->IsNumeric())
{
- SCSIZE nCount = pMat->GetElementCount();
- aArray.reserve(nCount);
for (SCSIZE i = 0; i < nCount; ++i)
aArray.push_back(pMat->GetDouble(i));
- pMat->GetDimensions(rCol, rRow);
}
else
- SetError(FormulaError::IllegalParameter);
+ {
+ for (SCSIZE i = 0; i < nCount; ++i)
+ {
+ if (pMat->IsValue(i))
+ aArray.push_back( pMat->GetDouble(i));
+ else
+ aArray.push_back( CreateDoubleError( FormulaError::NoValue));
+ }
+ }
+ pMat->GetDimensions(rCol, rRow);
}
break;
default:
+ PopError();
SetError(FormulaError::IllegalParameter);
break;
}