sc/source/core/opencl/op_statistical.cxx |  382 ++++++-------------------------
 sc/source/core/opencl/opbase.cxx         |   94 ++++++-
 sc/source/core/opencl/opbase.hxx         |   15 -
 3 files changed, 170 insertions(+), 321 deletions(-)

New commits:
commit 0513d1954c37f62cfb5336a640d3c336d3641e84
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Mon Sep 19 17:50:55 2022 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Tue Sep 20 08:45:30 2022 +0200

    reduce opencl copy&paste when handling a pair of svDoubleVectorRef
    
    Some functions run one loop iterating two svDoubleVectorRef.
    
    Change-Id: I849becd7863a1740277e6da9625bc7daad4b5274
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140191
    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 9f14c0bbdd40..29e150de10cd 100644
--- a/sc/source/core/opencl/op_statistical.cxx
+++ b/sc/source/core/opencl/op_statistical.cxx
@@ -154,311 +154,89 @@ void OpTTest::GenSlidingWindowFunction(outputstream &ss,
     ss << "    double fSumSqr2 = 0.0;\n";
     ss << "    double fCount1 = 0.0;\n";
     ss << "    double fCount2 = 0.0;\n";
-    ss << "    double arg1 = 0.0;\n";
-    ss << "    double arg2 = 0.0;\n";
-    ss << "    double mode = 0.0;\n";
-    ss << "    double type = 0.0;\n";
     ss << "    double fT = 0.0;\n";
     ss << "    double fF = 0.0;\n";
-    if(vSubArguments.size() != 4)
-    {
-        ss << "    return DBL_MAX;\n";
-        ss << "}\n";
-        return ;
-    }
-    if(vSubArguments.size() == 4)
-    {
-        FormulaToken *pCur  = vSubArguments[0]->GetFormulaToken();
-        FormulaToken *pCur1 = vSubArguments[1]->GetFormulaToken();
-        FormulaToken *pCur2 = vSubArguments[2]->GetFormulaToken();
-        FormulaToken *pCur3 = vSubArguments[3]->GetFormulaToken();
-        assert(pCur);
-        assert(pCur1);
-        assert(pCur2);
-        assert(pCur3);
-        if(ocPush == vSubArguments[2]->GetFormulaToken()->GetOpCode())
-        {
-            if(pCur2->GetType() == formula::svSingleVectorRef)
-            {
-                const formula::SingleVectorRefToken* pSVR =
-                    static_cast< const formula::SingleVectorRefToken*>(pCur2);
-                ss << "    if (gid0 < " << pSVR->GetArrayLength() << ")\n";
-                ss << "    {\n";
-                ss << "        mode = " ;
-                ss << vSubArguments[2]->GenSlidingWindowDeclRef() << ";\n";
-                ss << "        if (isnan(mode))\n";
-                ss << "            mode = 0.0;\n";
-                ss << "        else\n";
-                ss << "            mode = floor(mode);\n";
-                ss << "    }\n";
-            }
-            else if(pCur2->GetType() == formula::svDouble)
-            {
-                ss << "    mode = floor(convert_double(";
-                ss << pCur2->GetDouble() << "));\n";
-            }
-            else
-            {
-                ss << "    return DBL_MAX;\n";
-                ss << "}\n";
-                return ;
-            }
-        }
-        else
-        {
-            ss << "    mode = floor(" ;
-            ss << vSubArguments[2]->GenSlidingWindowDeclRef() << ");\n";
-        }
-        ss << "    if(!(mode == 1.0 || mode == 2.0))\n";
-        ss << "        return DBL_MAX;\n";
-        if(ocPush==vSubArguments[3]->GetFormulaToken()->GetOpCode())
-        {
-            if(pCur3->GetType() == formula::svSingleVectorRef)
-            {
-                const formula::SingleVectorRefToken* pSVR =
-                    static_cast< const formula::SingleVectorRefToken*>(pCur3);
-                assert(pSVR);
-                ss << "    if (gid0 < " << pSVR->GetArrayLength() << ")\n";
-                ss << "    {\n";
-                ss << "        if (isnan(";
-                ss << vSubArguments[3]->GenSlidingWindowDeclRef() << "))\n";
-                ss << "            type=0.0;\n";
-                ss << "        else\n";
-                ss << "            type=floor(";
-                ss << vSubArguments[3]->GenSlidingWindowDeclRef() << ");\n";
-                ss << "    }\n";
-            }
-            else if(pCur3->GetType() == formula::svDouble)
-            {
-                ss << "    type = floor(convert_double(" << pCur3->GetDouble() 
<<
-                "));\n";
-            }
-            else
-            {
-                ss << "    return DBL_MAX;\n";
-                ss << "}\n";
-                return ;
-            }
-        }
-        else
-        {
-            ss << "    type=floor(";
-            ss << vSubArguments[3]->GenSlidingWindowDeclRef() << ");\n";
-        }
-        ss << "    if(!(type == 1.0||type == 2.0||type == 3.0))\n";
-        ss << "        return DBL_MAX;\n";
-
-        if(pCur->GetType() == formula::svDoubleVectorRef &&
-               pCur1->GetType() == formula::svDoubleVectorRef)
-        {
-            const formula::DoubleVectorRefToken* pDVR =
-                static_cast<const formula::DoubleVectorRefToken *>(pCur);
-            const formula::DoubleVectorRefToken* pDVR1 =
-                static_cast<const formula::DoubleVectorRefToken *>(pCur1);
-
-            size_t nCurWindowSize  = pDVR->GetRefRowSize();
-            size_t nCurWindowSize1 = pDVR1->GetRefRowSize();
-
-            if(nCurWindowSize == nCurWindowSize1)
-            {
-                ss << "    if(type == 1.0)\n";
-                ss << "    {\n";
-                ss << "        for (int i = ";
-                if ((!pDVR->IsStartFixed() && pDVR->IsEndFixed()) &&
-                         (!pDVR1->IsStartFixed() && pDVR1->IsEndFixed()))
-                {
-                    ss << "gid0; i < " << pDVR->GetArrayLength();
-                    ss << " && i < " << nCurWindowSize  << "; i++)\n";
-                    ss << "        {\n";
-                }
-                else if ((pDVR->IsStartFixed() && !pDVR->IsEndFixed()) &&
-                             (pDVR1->IsStartFixed() && !pDVR1->IsEndFixed()))
-                {
-                    ss << "0; i < " << pDVR->GetArrayLength();
-                    ss << " && i < gid0+"<< nCurWindowSize << "; i++)\n";
-                    ss << "        {\n";
-                }
-                else if ((!pDVR->IsStartFixed() && !pDVR->IsEndFixed()) &&
-                             (!pDVR1->IsStartFixed() && !pDVR1->IsEndFixed()))
-                {
-                    ss << "0; i + gid0 < " << pDVR->GetArrayLength();
-                    ss << " &&  i < " << nCurWindowSize << "; i++)\n";
-                    ss << "        {\n";
-                }
-                else if ((pDVR->IsStartFixed() && pDVR->IsEndFixed()) &&
-                             (pDVR1->IsStartFixed() && pDVR1->IsEndFixed()))
-                {
-                    ss << "0; i < " << nCurWindowSize << "; i++)\n";
-                    ss << "        {\n";
-                }
-                else
-                {
-                    ss << "0; i < " << nCurWindowSize << "; i++)\n";
-                    ss << "        {\n";
-                    ss << "            break;\n";
-                    ss << "        }";
-                    ss << "        return DBL_MAX;\n";
-                    ss << "    }\n";
-                    ss << "}\n";
-                    return ;
-                }
-
-                ss << "            arg1 = ";
-                ss << vSubArguments[0]->GenSlidingWindowDeclRef(true) << ";\n";
-                ss << "            arg2 = ";
-                ss << vSubArguments[1]->GenSlidingWindowDeclRef(true) << ";\n";
-                ss << "            if (isnan(arg1)||isnan(arg2))\n";
-                ss << "                continue;\n";
-                ss << "            fSum1 += arg1;\n";
-                ss << "            fSum2 += arg2;\n";
-                ss << "            fSumSqr1 += (arg1 - arg2)*(arg1 - arg2);\n";
-                ss << "            fCount1 += 1;\n";
-                ss << "        }\n";
-                ss << "        if(fCount1 < 1.0)\n";
-                ss << "            return DBL_MAX;\n";
-                ss << "        fT = sqrt(fCount1-1.0) * fabs(fSum1 - fSum2)\n";
-                ss << "            /sqrt(fCount1 * fSumSqr1 - (fSum1-fSum2)\n";
-                ss << "             *(fSum1-fSum2));\n";
-                ss << "        fF = fCount1 - 1.0;\n";
-            }
-            else
-            {
-                ss << "    return DBL_MAX;\n";
-                ss << "}\n";
-                return ;
-            }
-        }
-        else
-        {
-            ss << "    return DBL_MAX;\n";
-            ss << "}\n";
-            return ;
-        }
-        ss << "    }\n";
-        ss << "    if(type == 2.0 || type == 3.0)\n";
-        ss << "    {\n";
-
-        if(pCur->GetType() == formula::svDoubleVectorRef &&
-               pCur1->GetType() == formula::svDoubleVectorRef)
-        {
-            const formula::DoubleVectorRefToken* pDVR =
-                static_cast<const formula::DoubleVectorRefToken *>(pCur);
-            const formula::DoubleVectorRefToken* pDVR1 =
-                static_cast<const formula::DoubleVectorRefToken *>(pCur1);
-
-            size_t nCurWindowSize  = pDVR->GetRefRowSize();
-            size_t nCurWindowSize1 = pDVR1->GetRefRowSize();
-            ss << "        for (int i = ";
-            if (!pDVR->IsStartFixed() && pDVR->IsEndFixed())
-            {
-                ss << "gid0; i < " << pDVR->GetArrayLength();
-                ss << " && i < " << nCurWindowSize  << "; i++)\n";
-                ss << "        {\n";
-            }
-            else if (pDVR->IsStartFixed() && !pDVR->IsEndFixed())
-            {
-                ss << "0; i < " << pDVR->GetArrayLength();
-                ss << " && i < gid0+"<< nCurWindowSize << "; i++)\n";
-                ss << "        {\n";
-            }
-            else if (!pDVR->IsStartFixed() && !pDVR->IsEndFixed())
-            {
-                ss << "0; i + gid0 < " << pDVR->GetArrayLength();
-                ss << " &&  i < " << nCurWindowSize << "; i++)\n";
-                ss << "        {\n";
-            }
-            else
-            {
-                ss << "0; i < " << nCurWindowSize << "; i++)\n";
-                ss << "        {\n";
-            }
-
-            ss << "            arg1 = ";
-            ss << vSubArguments[0]->GenSlidingWindowDeclRef(true) << ";\n";
-            ss << "            if (isnan(arg1))\n";
-            ss << "                continue;\n";
-            ss << "            fSum1 += arg1;\n";
-            ss << "            fSumSqr1 += arg1 * arg1;\n";
-            ss << "            fCount1 += 1;\n";
-            ss << "        }\n";
-
-            ss << "        for (int i = ";
-            if (!pDVR1->IsStartFixed() && pDVR1->IsEndFixed())
-            {
-                ss << "gid0; i < " << pDVR1->GetArrayLength();
-                ss << " && i < " << nCurWindowSize1  << "; i++)\n";
-                ss << "        {\n";
-            }
-            else if (pDVR1->IsStartFixed() && !pDVR1->IsEndFixed())
-            {
-                ss << "0; i < " << pDVR1->GetArrayLength();
-                ss << " && i < gid0+"<< nCurWindowSize1 << "; i++)\n";
-                ss << "        {\n";
-            }
-            else if (!pDVR1->IsStartFixed() && !pDVR1->IsEndFixed())
-            {
-                ss << "0; i + gid0 < " << pDVR1->GetArrayLength();
-                ss << " &&  i < " << nCurWindowSize1 << "; i++)\n";
-                ss << "        {\n";
-            }
-            else
-            {
-                ss << "0; i < " << nCurWindowSize1 << "; i++)\n";
-                ss << "        {\n";
-            }
-            ss << "            arg2 = ";
-            ss << vSubArguments[1]->GenSlidingWindowDeclRef(true) << ";\n";
-            ss << "            if (isnan(arg2))\n";
-            ss << "                continue;\n";
-            ss << "            fSum2 += arg2;\n";
-            ss << "            fSumSqr2 += arg2 * arg2;\n";
-            ss << "            fCount2 += 1;\n";
-            ss << "        }\n";
-        }
-        else
-        {
-            ss << "        return DBL_MAX;\n";
-            ss << "    }\n";
-            ss << "}\n";
-            return ;
-        }
-        ss << "        if (fCount1 < 2.0 || fCount2 < 2.0)\n";
-        ss << "            return DBL_MAX;\n";
-        ss << "    }\n";
-        ss << "    if(type == 3.0)\n";
-        ss << "    {\n";
-        ss << "        double fS1 = (fSumSqr1-fSum1*fSum1/fCount1)\n";
-        ss << "            /(fCount1-1.0)/fCount1;\n";
-        ss << "        double fS2 = (fSumSqr2-fSum2*fSum2/fCount2)\n";
-        ss << "            /(fCount2-1.0)/fCount2;\n";
-        ss << "        if (fS1 + fS2 == 0.0)\n";
-        ss << "            return DBL_MAX;\n";
-        ss << "        fT = fabs(fSum1/fCount1 - fSum2/fCount2)\n";
-        ss << "             /sqrt(fS1+fS2);\n";
-        ss << "        double c = fS1/(fS1+fS2);\n";
-        ss << "        fF = 1.0/(c*c/(fCount1-1.0)+(1.0-c)*(1.0-c)\n";
-        ss << "             /(fCount2-1.0));\n";
-        ss << "    }\n";
-        ss << "    if(type == 2.0)\n";
-        ss << "    {\n";
-        ss << "        double fS1 = (fSumSqr1 - fSum1*fSum1/fCount1)\n";
-        ss << "             /(fCount1 - 1.0);\n";
-        ss << "        double fS2 = (fSumSqr2 - fSum2*fSum2/fCount2)\n";
-        ss << "             /(fCount2 - 1.0);\n";
-        ss << "        fT = fabs( fSum1/fCount1 - fSum2/fCount2 )\n";
-        ss << "            /sqrt( (fCount1-1.0)*fS1 + (fCount2-1.0)*fS2 )\n";
-        ss << "            *sqrt( fCount1*fCount2*(fCount1+fCount2-2)\n";
-        ss << "            /(fCount1+fCount2) );\n";
-        ss << "        fF = fCount1 + fCount2 - 2;\n";
-        ss << "    }\n";
+    GenerateArg( "mode", 2, vSubArguments, ss );
+    GenerateArg( "type", 3, vSubArguments, ss );
+    ss << "    mode = floor(mode);\n";
+    ss << "    type = floor(type);\n";
+    ss << "    if(mode != 1.0 && mode != 2.0)\n";
+    ss << "        return CreateDoubleError(IllegalArgument);\n";
+    ss << "    if(type != 1.0 && type != 2.0 && type != 3.0)\n";
+    ss << "        return CreateDoubleError(IllegalArgument);\n";
 
-        ss << "    double tdist=GetTDist(fT, fF);\n";
-        ss << "    if (mode==1)\n";
-        ss << "        return tdist;\n";
-        ss << "    else\n";
-        ss << "        return 2.0*tdist;\n";
-        ss << "}\n";
-    }
+    ss << "    if(type == 1.0)\n";
+    ss << "    {\n";
+    GenerateRangeArgPair( 0, 1, vSubArguments, ss,
+        "            if (!isnan(arg1) && !isnan(arg2))\n"
+        "            {\n"
+        "                fSum1 += arg1;\n"
+        "                fSum2 += arg2;\n"
+        "                fSumSqr1 += (arg1 - arg2)*(arg1 - arg2);\n"
+        "                fCount1 += 1;\n"
+        "            }\n"
+        );
+    ss << "        if(fCount1 < 1.0)\n";
+    ss << "            return CreateDoubleError(NoValue);\n";
+    ss << "        double divider = sqrt(fCount1 * fSumSqr1 - 
(fSum1-fSum2)*(fSum1-fSum2));\n";
+    ss << "        if(divider == 0)\n";
+    ss << "            return CreateDoubleError(DivisionByZero);\n";
+    ss << "        fT = sqrt(fCount1-1.0) * fabs(fSum1 - fSum2) / divider;\n";
+    ss << "        fF = fCount1 - 1.0;\n";
+    ss << "    }\n";
+    ss << "    if(type == 2.0 || type == 3.0)\n";
+    ss << "    {\n";
+    GenerateRangeArg( 0, vSubArguments, ss,
+        "        if (!isnan(arg))\n"
+        "        {\n"
+        "            fSum1 += arg;\n"
+        "            fSumSqr1 += arg * arg;\n"
+        "            fCount1 += 1;\n"
+        "        }\n"
+        );
+    GenerateRangeArg( 1, vSubArguments, ss,
+        "        if (!isnan(arg))\n"
+        "        {\n"
+        "            fSum2 += arg;\n"
+        "            fSumSqr2 += arg * arg;\n"
+        "            fCount2 += 1;\n"
+        "        }\n"
+        );
+    ss << "        if (fCount1 < 2.0 || fCount2 < 2.0)\n";
+    ss << "            return CreateDoubleError(NoValue);\n";
+    ss << "    }\n";
+    ss << "    if(type == 3.0)\n";
+    ss << "    {\n";
+    ss << "        double fS1 = (fSumSqr1-fSum1*fSum1/fCount1)\n";
+    ss << "            /(fCount1-1.0)/fCount1;\n";
+    ss << "        double fS2 = (fSumSqr2-fSum2*fSum2/fCount2)\n";
+    ss << "            /(fCount2-1.0)/fCount2;\n";
+    ss << "        if (fS1 + fS2 == 0.0)\n";
+    ss << "            return CreateDoubleError(NoValue);\n";
+    ss << "        fT = fabs(fSum1/fCount1 - fSum2/fCount2)\n";
+    ss << "             /sqrt(fS1+fS2);\n";
+    ss << "        double c = fS1/(fS1+fS2);\n";
+    ss << "        fF = 1.0/(c*c/(fCount1-1.0)+(1.0-c)*(1.0-c)\n";
+    ss << "             /(fCount2-1.0));\n";
+    ss << "    }\n";
+    ss << "    if(type == 2.0)\n";
+    ss << "    {\n";
+    ss << "        double fS1 = (fSumSqr1 - fSum1*fSum1/fCount1)\n";
+    ss << "             /(fCount1 - 1.0);\n";
+    ss << "        double fS2 = (fSumSqr2 - fSum2*fSum2/fCount2)\n";
+    ss << "             /(fCount2 - 1.0);\n";
+    ss << "        fT = fabs( fSum1/fCount1 - fSum2/fCount2 )\n";
+    ss << "            /sqrt( (fCount1-1.0)*fS1 + (fCount2-1.0)*fS2 )\n";
+    ss << "            *sqrt( fCount1*fCount2*(fCount1+fCount2-2)\n";
+    ss << "            /(fCount1+fCount2) );\n";
+    ss << "        fF = fCount1 + fCount2 - 2;\n";
+    ss << "    }\n";
+    ss << "    double tdist=GetTDist(fT, fF);\n";
+    ss << "    if (mode==1)\n";
+    ss << "        return tdist;\n";
+    ss << "    else\n";
+    ss << "        return 2.0*tdist;\n";
+    ss << "}\n";
 }
 
 void OpTDist::BinInlineFun(std::set<std::string>& decls,
diff --git a/sc/source/core/opencl/opbase.cxx b/sc/source/core/opencl/opbase.cxx
index c85d3dec8764..c73e50b3c593 100644
--- a/sc/source/core/opencl/opbase.cxx
+++ b/sc/source/core/opencl/opbase.cxx
@@ -174,10 +174,10 @@ bool VectorRef::NeedParallelReduction() const
     return false;
 }
 
-void SlidingFunctionBase::GenerateArg( const char* name, int num, 
SubArguments& vSubArguments, outputstream& ss )
+void SlidingFunctionBase::GenerateArg( const char* name, int arg, 
SubArguments& vSubArguments, outputstream& ss )
 {
-    CHECK_PARAMETER_COUNT_MIN( num );
-    FormulaToken *token = vSubArguments[num]->GetFormulaToken();
+    assert( arg < int( vSubArguments.size()));
+    FormulaToken *token = vSubArguments[arg]->GetFormulaToken();
     if( token == nullptr )
         throw Unhandled( __FILE__, __LINE__ );
     ss << "    double " << name << ";\n";
@@ -188,11 +188,11 @@ void SlidingFunctionBase::GenerateArg( const char* name, 
int num, SubArguments&
             const formula::SingleVectorRefToken* svr =
                 static_cast<const formula::SingleVectorRefToken *>(token);
             ss << "    if (gid0 >= " << svr->GetArrayLength() << " || isnan(";
-            ss << vSubArguments[num]->GenSlidingWindowDeclRef() << "))\n";
+            ss << vSubArguments[arg]->GenSlidingWindowDeclRef() << "))\n";
             ss << "        " << name << " = 0.0;\n";
             ss << "    else\n";
             ss << "        " << name << " = ";
-            ss << vSubArguments[num]->GenSlidingWindowDeclRef() << ";\n";
+            ss << vSubArguments[arg]->GenSlidingWindowDeclRef() << ";\n";
         }
         else if(token->GetType() == formula::svDouble)
             ss << "    " << name << " = " << token->GetDouble() << ";\n";
@@ -202,22 +202,22 @@ void SlidingFunctionBase::GenerateArg( const char* name, 
int num, SubArguments&
     else
     {
         ss << "    " << name << " = ";
-        ss << vSubArguments[num]->GenSlidingWindowDeclRef() << ";\n";
+        ss << vSubArguments[arg]->GenSlidingWindowDeclRef() << ";\n";
     }
 }
 
-void SlidingFunctionBase::GenerateArg( int num, SubArguments& vSubArguments, 
outputstream& ss )
+void SlidingFunctionBase::GenerateArg( int arg, SubArguments& vSubArguments, 
outputstream& ss )
 {
     char buf[ 30 ];
-    sprintf( buf, "arg%d", num );
-    GenerateArg( buf, num, vSubArguments, ss );
+    sprintf( buf, "arg%d", arg );
+    GenerateArg( buf, arg, vSubArguments, ss );
 }
 
-void SlidingFunctionBase::GenerateArgWithDefault( const char* name, int num, 
double def,
+void SlidingFunctionBase::GenerateArgWithDefault( const char* name, int arg, 
double def,
     SubArguments& vSubArguments, outputstream& ss )
 {
-    if( int(vSubArguments.size()) > num )
-        GenerateArg( name, num, vSubArguments, ss );
+    if( arg < int(vSubArguments.size()))
+        GenerateArg( name, arg, vSubArguments, ss );
     else
         ss << "    double " << name << " = " << def << ";\n";
 }
@@ -226,6 +226,7 @@ void SlidingFunctionBase::GenerateRangeArgs( int firstArg, 
int lastArg, SubArgum
     outputstream& ss, const char* code )
 {
     assert( firstArg >= 0 );
+    assert( firstArg <= lastArg );
     assert( lastArg < int( vSubArguments.size()));
     for( int i = firstArg;
          i <= lastArg;
@@ -307,10 +308,75 @@ void SlidingFunctionBase::GenerateRangeArgs( 
SubArguments& vSubArguments,
     GenerateRangeArgs( 0, vSubArguments.size() - 1, vSubArguments, ss, code );
 }
 
-void SlidingFunctionBase::GenerateRangeArg( int num, SubArguments& 
vSubArguments,
+void SlidingFunctionBase::GenerateRangeArg( int arg, SubArguments& 
vSubArguments,
     outputstream& ss, const char* code )
 {
-    GenerateRangeArgs( num, num, vSubArguments, ss, code );
+    GenerateRangeArgs( arg, arg, vSubArguments, ss, code );
+}
+
+void SlidingFunctionBase::GenerateRangeArgPair( int arg1, int arg2, 
SubArguments& vSubArguments,
+    outputstream& ss, const char* code )
+{
+    assert( arg1 >= 0 && arg1 < int (vSubArguments.size()));
+    assert( arg2 >= 0 && arg2 < int (vSubArguments.size()));
+    assert( arg1 != arg2 );
+    FormulaToken *token1 = vSubArguments[arg1]->GetFormulaToken();
+    if( token1 == nullptr )
+        throw Unhandled( __FILE__, __LINE__ );
+    FormulaToken *token2 = vSubArguments[arg2]->GetFormulaToken();
+    if( token2 == nullptr )
+        throw Unhandled( __FILE__, __LINE__ );
+    if(token1->GetType() != formula::svDoubleVectorRef
+        || token2->GetType() != formula::svDoubleVectorRef)
+    {
+        throw Unhandled( __FILE__, __LINE__ );
+    }
+    const formula::DoubleVectorRefToken* pDVR1 =
+        static_cast<const formula::DoubleVectorRefToken *>(token1);
+    const formula::DoubleVectorRefToken* pDVR2 =
+        static_cast<const formula::DoubleVectorRefToken *>(token2);
+
+    size_t nCurWindowSize1  = pDVR1->GetRefRowSize();
+    size_t nCurWindowSize2 = pDVR2->GetRefRowSize();
+
+    if(nCurWindowSize1 != nCurWindowSize2)
+        throw Unhandled( __FILE__, __LINE__ );
+    if(pDVR1->IsStartFixed() != pDVR2->IsStartFixed()
+        || pDVR1->IsEndFixed() != pDVR2->IsEndFixed())
+    {
+        throw Unhandled( __FILE__, __LINE__ );
+    }
+
+    ss << "    for (int i = ";
+    if (!pDVR1->IsStartFixed() && pDVR1->IsEndFixed())
+    {
+        ss << "gid0; i < " << pDVR1->GetArrayLength();
+        ss << " && i < " << nCurWindowSize1  << "; i++)\n";
+        ss << "    {\n";
+    }
+    else if (pDVR1->IsStartFixed() && !pDVR1->IsEndFixed())
+    {
+        ss << "0; i < " << pDVR1->GetArrayLength();
+        ss << " && i < gid0+"<< nCurWindowSize1 << "; i++)\n";
+        ss << "    {\n";
+    }
+    else if (!pDVR1->IsStartFixed() && !pDVR1->IsEndFixed())
+    {
+        ss << "0; i + gid0 < " << pDVR1->GetArrayLength();
+        ss << " &&  i < " << nCurWindowSize1 << "; i++)\n";
+        ss << "    {\n";
+    }
+    else
+    {
+        ss << "0; i < " << nCurWindowSize1 << "; i++)\n";
+        ss << "    {\n";
+    }
+    ss << "        double arg1 = ";
+    ss << vSubArguments[arg1]->GenSlidingWindowDeclRef(true) << ";\n";
+    ss << "        double arg2 = ";
+    ss << vSubArguments[arg2]->GenSlidingWindowDeclRef(true) << ";\n";
+    ss << code;
+    ss << "    }\n";
 }
 
 void SlidingFunctionBase::GenerateFunctionDeclaration( const std::string& 
sSymName,
diff --git a/sc/source/core/opencl/opbase.hxx b/sc/source/core/opencl/opbase.hxx
index 7b2283865ee2..c9ab020d6689 100644
--- a/sc/source/core/opencl/opbase.hxx
+++ b/sc/source/core/opencl/opbase.hxx
@@ -255,12 +255,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 num, SubArguments& 
vSubArguments, outputstream& ss );
-    // overload, variable will be named "arg<num>"
-    static void GenerateArg( int num, SubArguments& vSubArguments, 
outputstream& ss );
+    static 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 );
     // generate code for "double <name> = <value>;" from vSubArguments, if it 
exists,
     // otherwise set to <def>
-    static void GenerateArgWithDefault( const char* name, int num, double def, 
SubArguments& vSubArguments,
+    static void GenerateArgWithDefault( const char* name, int arg, double def, 
SubArguments& vSubArguments,
         outputstream& ss );
     void GenerateFunctionDeclaration( const std::string& sSymName,
         SubArguments& vSubArguments, outputstream& ss );
@@ -272,7 +272,12 @@ protected:
     // overload, handle all arguments
     static void GenerateRangeArgs( SubArguments& vSubArguments, outputstream& 
ss, const char* code );
     // overload, handle the given argument
-    static void GenerateRangeArg( int num, SubArguments& vSubArguments, 
outputstream& ss, const char* code );
+    static void GenerateRangeArg( int arg, SubArguments& vSubArguments, 
outputstream& ss, const char* code );
+    // 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'.
+    // Both arguments must be svDoubleRef of the same size.
+    static void GenerateRangeArgPair( int arg1, int arg2, SubArguments& 
vSubArguments,
+        outputstream& ss, const char* code );
 };
 
 class Normal : public SlidingFunctionBase

Reply via email to