diff options
author | Eike Rathke <erack@redhat.com> | 2023-03-03 13:39:03 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2023-03-04 20:53:42 +0000 |
commit | 6e0c8a3dbdb83b634a30dad018e1ff5f9959d055 (patch) | |
tree | de12be538a57ab954e46d19f6e4e6dc70f5a10e7 | |
parent | b9d88aa83709708dc43c606e1357965e7ea993fc (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
(cherry picked from commit 019e751c71dcb2d34c6fd8bb9dda267c6ba2b48e)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148218
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r-- | sc/source/core/tool/interpr3.cxx | 44 |
1 files changed, 32 insertions, 12 deletions
diff --git a/sc/source/core/tool/interpr3.cxx b/sc/source/core/tool/interpr3.cxx index e9100d76149d..1fa4500a9baf 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; } |