sc/qa/unit/data/functions/fods/Functions_Excel_2016.fods | 2 - sc/source/core/opencl/op_logical.hxx | 3 + sc/source/core/opencl/op_statistical.cxx | 24 ++++++++++----- sc/source/core/opencl/opbase.cxx | 4 +- sc/source/core/opencl/opbase.hxx | 12 ++++--- 5 files changed, 29 insertions(+), 16 deletions(-)
New commits: commit 7dc92d60166a99e0539ce83ecf45bb40fd30d784 Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Tue Sep 20 09:57:38 2022 +0200 Commit: Luboš Luňák <l.lu...@collabora.com> CommitDate: Tue Sep 20 17:53:32 2022 +0200 fix opencl AND() to treat empty cell in svSingleVectorRef as core does Functions_Excel_2016.fods incorrectly used "=AND(Sheet2.C22;C33)" instead of the correct "=AND(Sheet2.C22:C33)" (colon vs semicolon), and C33 is an empty cell. The return however was true because empty cells get special treatment because of Excel compatibility. Change-Id: I6d0b28280059fd6fc945e77c7b5d714b5e4727a2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140224 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> diff --git a/sc/qa/unit/data/functions/fods/Functions_Excel_2016.fods b/sc/qa/unit/data/functions/fods/Functions_Excel_2016.fods index f5c2aedd3abe..b4a6ea11500d 100644 --- a/sc/qa/unit/data/functions/fods/Functions_Excel_2016.fods +++ b/sc/qa/unit/data/functions/fods/Functions_Excel_2016.fods @@ -856,7 +856,7 @@ <table:table-cell office:value-type="float" office:value="1" calcext:value-type="float"> <text:p>1</text:p> </table:table-cell> - <table:table-cell table:style-name="ce12" table:formula="of:=AND([Sheet2.C22];[.C33])" office:value-type="boolean" office:boolean-value="true" calcext:value-type="boolean"> + <table:table-cell table:style-name="ce12" table:formula="of:=AND([Sheet2.C22]:[.C33])" office:value-type="boolean" office:boolean-value="true" calcext:value-type="boolean"> <text:p>WAAR</text:p> </table:table-cell> <table:table-cell office:value-type="string" calcext:value-type="string"> diff --git a/sc/source/core/opencl/op_logical.hxx b/sc/source/core/opencl/op_logical.hxx index f4c6b7a952ef..a52d1db0cf86 100644 --- a/sc/source/core/opencl/op_logical.hxx +++ b/sc/source/core/opencl/op_logical.hxx @@ -32,6 +32,9 @@ public: virtual std::string BinFuncName() const override { return "And"; } virtual const char* openclOperator() const override { return "&&"; }; virtual const char* defaultOpenclValue() const override { return "true"; } + // AND() with a svSingleVectorRef pointing to an empty cell skips that cell. + // See ScInterpreter::ScAnd(). + virtual const char* rangeEmptyCellValue() const override { return "1.0"; }; }; class OpOr: public OpLogicalBinaryOperator diff --git a/sc/source/core/opencl/opbase.cxx b/sc/source/core/opencl/opbase.cxx index 2cb51e47d080..fe98b4c09dd3 100644 --- a/sc/source/core/opencl/opbase.cxx +++ b/sc/source/core/opencl/opbase.cxx @@ -189,7 +189,7 @@ void SlidingFunctionBase::GenerateArg( const char* name, int arg, SubArguments& static_cast<const formula::SingleVectorRefToken *>(token); ss << " if (gid0 >= " << svr->GetArrayLength() << " || isnan("; ss << vSubArguments[arg]->GenSlidingWindowDeclRef() << "))\n"; - ss << " " << name << " = 0.0;\n"; + ss << " " << name << " = " << rangeEmptyCellValue() << ";\n"; ss << " else\n"; ss << " " << name << " = "; ss << vSubArguments[arg]->GenSlidingWindowDeclRef() << ";\n"; @@ -345,7 +345,7 @@ void SlidingFunctionBase::GenerateRangeArgElement( const char* name, int arg, co throw Unhandled( __FILE__, __LINE__ ); const formula::DoubleVectorRefToken* pDVR = static_cast<const formula::DoubleVectorRefToken *>(token); - ss << " double " << name << " = NAN;\n"; + ss << " double " << name << " = " << rangeEmptyCellValue() << ";\n"; ss << " {\n"; // GenSlidingWindowDeclRef() may refer to 'i' variable. ss << " int i = 0;\n"; diff --git a/sc/source/core/opencl/opbase.hxx b/sc/source/core/opencl/opbase.hxx index ee55d72c45b6..aa2770cd20aa 100644 --- a/sc/source/core/opencl/opbase.hxx +++ b/sc/source/core/opencl/opbase.hxx @@ -261,12 +261,12 @@ public: const std::string&, SubArguments& ) = 0; protected: // generate code for "double <name> = <value>;" from vSubArguments, svDoubleVectorRef is not supported - static void GenerateArg( const char* name, int arg, SubArguments& vSubArguments, outputstream& ss ); + void GenerateArg( const char* name, int arg, SubArguments& vSubArguments, outputstream& ss ); // overload, variable will be named "arg<arg>" - static void GenerateArg( int arg, SubArguments& vSubArguments, outputstream& ss ); + void GenerateArg( int arg, SubArguments& vSubArguments, outputstream& ss ); // generate code for "double <name> = <value>;" from vSubArguments, if it exists, // otherwise set to <def> - static void GenerateArgWithDefault( const char* name, int arg, double def, SubArguments& vSubArguments, + void GenerateArgWithDefault( const char* name, int arg, double def, SubArguments& vSubArguments, outputstream& ss ); void GenerateFunctionDeclaration( const std::string& sSymName, SubArguments& vSubArguments, outputstream& ss ); @@ -282,7 +282,7 @@ protected: // Overload. // Both arguments must be svDoubleRef of the same size. // If 'firstElementDiff' is set, the loop start will be offset by '+ firstElementDiff'. - static void GenerateRangeArg( int arg1, int arg2, SubArguments& vSubArguments, + void GenerateRangeArg( int arg1, int arg2, SubArguments& vSubArguments, outputstream& ss, const char* code, const char* firstElementDiff = nullptr ); // Generate code that will handle the given two arguments in one loop where n-th element of arg1 and arg2 // will be handled at the same time, named 'arg1' and 'arg2'. @@ -293,10 +293,12 @@ protected: // Generate code for "double <name> = range[<element>]" from vSubArguments. // The argument must be svDoubleRef. // There is no isnan(arg) checking. - static void GenerateRangeArgElement( const char* name, int arg, const char* element, + void GenerateRangeArgElement( const char* name, int arg, const char* element, SubArguments& vSubArguments, outputstream& ss ); static void GenerateDoubleVectorLoopHeader( outputstream& ss, const formula::DoubleVectorRefToken* pDVR, const char* firstElementDiff ); + // The default value when there is an empty cell in a range (or it's out of bounds). + virtual const char* rangeEmptyCellValue() const { return "0.0"; }; }; class Normal : public SlidingFunctionBase commit 7c86dd5819be4ebb3599a654b69d3416dcbb6138 Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Tue Sep 20 09:57:34 2022 +0200 Commit: Luboš Luňák <l.lu...@collabora.com> CommitDate: Tue Sep 20 17:53:19 2022 +0200 fix opencl FTEST() Change-Id: I72a6e7e36a8514c1d3c824a70829ebf026659262 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140223 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> diff --git a/sc/source/core/opencl/op_statistical.cxx b/sc/source/core/opencl/op_statistical.cxx index c1bef2b9c612..f2d32c7eefa1 100644 --- a/sc/source/core/opencl/op_statistical.cxx +++ b/sc/source/core/opencl/op_statistical.cxx @@ -2252,12 +2252,15 @@ void OpFTest::GenSlidingWindowFunction(outputstream &ss, ss << " double fSumSqr1 = 0.0;\n"; ss << " double fSum2 = 0.0;\n"; ss << " double fSumSqr2 = 0.0;\n"; + ss << " double fLength1 = 0.0;\n"; + ss << " double fLength2 = 0.0;\n"; ss << " double tmp = 0;\n"; GenerateRangeArg( 0, vSubArguments, ss, " if( !isnan(arg))\n" " {\n" " fSum1 += arg;\n" " fSumSqr1 += arg * arg;\n" + " fLength1 += 1;\n" " }\n" ); GenerateRangeArg( 1, vSubArguments, ss, @@ -2265,25 +2268,30 @@ void OpFTest::GenSlidingWindowFunction(outputstream &ss, " {\n" " fSum2 += arg;\n" " fSumSqr2 += arg * arg;\n" + " fLength2 += 1;\n" " }\n" ); - ss << " double fS1 = (fSumSqr1-fSum1*fSum1/length0)/(length0-1.0);\n" - " double fS2 = (fSumSqr2-fSum2*fSum2/length1)/(length1-1.0);\n" + ss << " if(fLength1 < 2 || fLength2 < 2)\n" + " return CreateDoubleError(NoValue);\n" + " double fS1 = (fSumSqr1-fSum1*fSum1/fLength1)/(fLength1-1.0);\n" + " double fS2 = (fSumSqr2-fSum2*fSum2/fLength2)/(fLength2-1.0);\n" + " if(fS1 == 0 || fS2 == 0)\n" + " return CreateDoubleError(NoValue);\n" " double fF, fF1, fF2;\n" " if (fS1 > fS2)\n" " {\n" " fF = fS1/fS2;\n" - " fF1 = length0-1.0;\n" - " fF2 = length1-1.0;\n" + " fF1 = fLength1-1.0;\n" + " fF2 = fLength2-1.0;\n" " }\n" " else\n" " {\n" " fF = fS2/fS1;\n" - " fF1 = length1-1.0;\n" - " fF2 = length0-1.0;\n" + " fF1 = fLength2-1.0;\n" + " fF2 = fLength1-1.0;\n" " }\n" - " tmp = 2.0*GetFDist(fF, fF1, fF2);\n"; - ss << " return tmp;\n"; + " double fFcdf = GetFDist(fF, fF1, fF2);\n" + " return 2.0*min(fFcdf, 1 - fFcdf);\n"; ss << "}"; } void OpB::BinInlineFun(std::set<std::string>& decls,