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,

Reply via email to