diff options
author | Caolán McNamara <caolan.mcnamara@collabora.com> | 2023-08-19 16:42:25 +0100 |
---|---|---|
committer | Caolán McNamara <caolan.mcnamara@collabora.com> | 2023-08-19 20:55:08 +0200 |
commit | 81c19355d7ad830c2356d7d82e244929be3823a8 (patch) | |
tree | 66e08948c3d8b02c4dad3d733df022af3eb25cd9 | |
parent | f9d5887697405e600cb85cd49b0ce1d8e63cdc27 (diff) |
crashtesting: parallel calc assert with Lookup
seen in forum-mso-en4-55192.xlsx with a singlecell as the result vector
which gets autoextended outside the range that the pre-parallel calc
took into consideration on set up. For simplicity if there is a result
vector assume that if it doesn't match the size of the search vector
that we can't parallelize this.
Change-Id: Ic67e1b5b35964760ac5b1608cd516a69e08d0540
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155862
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 4b974831992b..85d43700461e 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -4432,6 +4432,52 @@ struct ScDependantsCalculator return nRowLen; } + // Because Lookup will extend the Result Vector under certain cirumstances listed at: + // https://wiki.documentfoundation.org/Documentation/Calc_Functions/LOOKUP + // then if the Lookup has a Result Vector only accept the Lookup for parallelization + // of the Result Vector has the same dimensions as the Search Vector. + bool LookupResultVectorMismatch(sal_Int32 nTokenIdx) + { + if (nTokenIdx >= 3) + { + FormulaToken** pRPNArray = mrCode.GetCode(); + if (pRPNArray[nTokenIdx - 1]->GetOpCode() == ocPush && // <- result vector + pRPNArray[nTokenIdx - 2]->GetOpCode() == ocPush && // <- search vector + pRPNArray[nTokenIdx - 2]->GetType() == svDoubleRef && + pRPNArray[nTokenIdx - 3]->GetOpCode() == ocPush) // <- search criterion + { + auto res = pRPNArray[nTokenIdx - 1]; + // If Result vector is just a single cell reference + // LOOKUP extends it as a column vector. + if (res->GetType() == svSingleRef) + return true; + + // If Result vector is a cell range and the match position + // falls outside its length, it gets automatically extended + // to the length of Search vector, but in the direction of + // Result vector. + if (res->GetType() == svDoubleRef) + { + ScComplexRefData aRef1 = *res->GetDoubleRef(); + ScComplexRefData aRef2 = *pRPNArray[nTokenIdx - 2]->GetDoubleRef(); + ScRange resultRange = aRef1.toAbs(mrDoc, mrPos); + ScRange sourceRange = aRef2.toAbs(mrDoc, mrPos); + + SCROW nResultRows = resultRange.aEnd.Row() - resultRange.aStart.Row(); + SCROW nSourceRows = sourceRange.aEnd.Row() - sourceRange.aStart.Row(); + if (nResultRows != nSourceRows) + return true; + + SCCOL nResultCols = resultRange.aEnd.Col() - resultRange.aStart.Col(); + SCCOL nSourceCols = sourceRange.aEnd.Col() - sourceRange.aStart.Col(); + if (nResultCols != nSourceCols) + return true; + } + } + } + return false; + } + bool DoIt(ScRangeList* pSuccessfulDependencies, ScAddress* pDirtiedAddress) { // Partially from ScGroupTokenConverter::convert in sc/source/core/data/grouptokenconverter.cxx @@ -4460,6 +4506,12 @@ struct ScDependantsCalculator return false; } + if (p->GetOpCode() == ocLookup && LookupResultVectorMismatch(nTokenIdx)) + { + SAL_INFO("sc.core.formulacell", "Lookup Result Vector size doesn't match Search Vector"); + return false; + } + switch (p->GetType()) { case svSingleRef: |