summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolan.mcnamara@collabora.com>2023-08-19 16:42:25 +0100
committerCaolán McNamara <caolan.mcnamara@collabora.com>2023-08-19 20:55:08 +0200
commit81c19355d7ad830c2356d7d82e244929be3823a8 (patch)
tree66e08948c3d8b02c4dad3d733df022af3eb25cd9
parentf9d5887697405e600cb85cd49b0ce1d8e63cdc27 (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.cxx52
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: