diff --git a/sc/source/core/opencl/op_statistical.cxx b/sc/source/core/opencl/op_statistical.cxx index cdbfe8b10679..aedabb4fc14c 100644 --- a/sc/source/core/opencl/op_statistical.cxx +++ b/sc/source/core/opencl/op_statistical.cxx @@ -19,6 +19,7 @@ namespace sc::opencl { void OpVar::GenSlidingWindowFunction(outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments) { + CHECK_PARAMETER_COUNT( 1, 30 ); GenerateFunctionDeclaration( sSymName, vSubArguments, ss ); ss << "{\n"; ss << " int gid0 = get_global_id(0);\n"; @@ -26,160 +27,18 @@ void OpVar::GenSlidingWindowFunction(outputstream &ss, ss << " double fMean = 0.0;\n"; ss << " double vSum = 0.0;\n"; ss << " double fCount = 0.0;\n"; - ss << " double arg = 0.0;\n"; - unsigned i = vSubArguments.size(); - while (i--) - { - FormulaToken *pCur = vSubArguments[i]->GetFormulaToken(); - assert(pCur); - if(ocPush == vSubArguments[i]->GetFormulaToken()->GetOpCode()) - { - if (pCur->GetType() == formula::svDoubleVectorRef) - { - const formula::DoubleVectorRefToken* pDVR = - static_cast(pCur); - size_t nCurWindowSize = pDVR->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 < " << pDVR->GetArrayLength() << "; i++)\n"; - ss << " {\n"; - } - ss << " arg = "; - ss << vSubArguments[i]->GenSlidingWindowDeclRef(); - ss << ";\n"; - ss << " if (isnan(arg))\n"; - ss << " continue;\n"; - ss << " fSum += arg;\n"; - ss << " fCount += 1.0;\n"; - ss << " }\n"; - } - else if (pCur->GetType() == formula::svSingleVectorRef) - { - const formula::SingleVectorRefToken* pSVR = - static_cast< const formula::SingleVectorRefToken*>(pCur); - ss << " if (gid0 < " << pSVR->GetArrayLength() << ")\n"; - ss << " {\n"; - ss << " arg = "; - ss << vSubArguments[i]->GenSlidingWindowDeclRef() << ";\n"; - ss << " if (!isnan(arg))\n"; - ss << " {\n"; - ss << " fSum += arg;\n"; - ss << " fCount += 1.0;\n"; - ss << " }\n"; - ss << " }\n"; - } - else - { - ss << " arg = " << pCur->GetDouble() << ";\n"; - ss << " fSum += arg;\n"; - ss << " fCount += 1.0;\n"; - } - } - else - { - ss << " arg = "; - ss << vSubArguments[i]->GenSlidingWindowDeclRef() << ";\n"; - ss << " fSum += arg;\n"; - ss << " fCount += 1.0;\n"; - } - if (i == 0) - { - ss << " fMean = fSum / fCount;\n"; - } - } - i = vSubArguments.size(); - while (i--) - { - FormulaToken *pCur = vSubArguments[i]->GetFormulaToken(); - assert(pCur); - if(ocPush == vSubArguments[i]->GetFormulaToken()->GetOpCode()) - { - if (pCur->GetType() == formula::svDoubleVectorRef) - { - const formula::DoubleVectorRefToken* pDVR = - static_cast(pCur); - size_t nCurWindowSize = pDVR->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 < " << pDVR->GetArrayLength() << "; i++)\n"; - ss << " {\n"; - } - - ss << " arg = "; - ss << vSubArguments[i]->GenSlidingWindowDeclRef(); - ss << ";\n"; - ss << " if (isnan(arg))\n"; - ss << " continue;\n"; - ss << " vSum += (arg - fMean) * (arg - fMean);\n"; - ss << " }\n"; - } - else if (pCur->GetType() == formula::svSingleVectorRef) - { - const formula::SingleVectorRefToken* pSVR = - static_cast< const formula::SingleVectorRefToken*>(pCur); - ss << " if (gid0 < " << pSVR->GetArrayLength() << ")\n"; - ss << " {\n"; - ss << " if (!isnan("; - ss << vSubArguments[i]->GenSlidingWindowDeclRef(); - ss << "))\n"; - ss << " {\n"; - ss << " arg = "; - ss << vSubArguments[i]->GenSlidingWindowDeclRef() << ";\n"; - ss << " vSum += (arg - fMean) * (arg - fMean);\n"; - ss << " }\n"; - ss << " }\n"; - } - else - { - ss << " arg=" << pCur->GetDouble() << ";\n"; - ss << " vSum += (arg - fMean) * (arg - fMean);\n"; - } - } - else - { - ss << " arg = "; - ss << vSubArguments[i]->GenSlidingWindowDeclRef() << ";\n"; - ss << " vSum += (arg - fMean) * (arg - fMean);\n"; - } - } + GenerateRangeArgs( vSubArguments, ss, + " if (!isnan(arg))\n" + " {\n" + " fSum += arg;\n" + " fCount += 1.0;\n" + " }\n" + ); + ss << " fMean = fSum / fCount;\n"; + GenerateRangeArgs( vSubArguments, ss, + " if (!isnan(arg))\n" + " vSum += (arg - fMean) * (arg - fMean);\n" + ); ss << " if (fCount <= 1.0)\n"; ss << " return CreateDoubleError(DivisionByZero);\n"; ss << " else\n"; diff --git a/sc/source/core/opencl/opbase.cxx b/sc/source/core/opencl/opbase.cxx index 512e3176bf43..393e532924a6 100644 --- a/sc/source/core/opencl/opbase.cxx +++ b/sc/source/core/opencl/opbase.cxx @@ -222,6 +222,91 @@ void SlidingFunctionBase::GenerateArgWithDefault( const char* name, int num, dou ss << " double " << name << " = " << def << ";\n"; } +void SlidingFunctionBase::GenerateRangeArgs( int firstArg, int lastArg, SubArguments& vSubArguments, + outputstream& ss, const char* code ) +{ + assert( firstArg >= 0 ); + assert( lastArg < int( vSubArguments.size())); + for( int i = firstArg; + i <= lastArg; + ++i ) + { + FormulaToken *token = vSubArguments[i]->GetFormulaToken(); + if( token == nullptr ) + throw Unhandled( __FILE__, __LINE__ ); + if(token->GetOpCode() == ocPush) + { + if (token->GetType() == formula::svDoubleVectorRef) + { + const formula::DoubleVectorRefToken* pDVR = + static_cast(token); + size_t nCurWindowSize = pDVR->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 < " << pDVR->GetArrayLength() << "; i++)\n"; + ss << " {\n"; + } + ss << " double arg = "; + ss << vSubArguments[i]->GenSlidingWindowDeclRef(); + ss << ";\n"; + ss << code; + ss << " }\n"; + } + else if (token->GetType() == formula::svSingleVectorRef) + { + const formula::SingleVectorRefToken* pSVR = + static_cast< const formula::SingleVectorRefToken*>(token); + ss << " if (gid0 < " << pSVR->GetArrayLength() << ")\n"; + ss << " {\n"; + ss << " double arg = "; + ss << vSubArguments[i]->GenSlidingWindowDeclRef() << ";\n"; + ss << code; + ss << " }\n"; + } + else + { + ss << " {\n"; + ss << " double arg = " << token->GetDouble() << ";\n"; + ss << code; + ss << " }\n"; + } + } + else + { + ss << " {\n"; + ss << " double arg = "; + ss << vSubArguments[i]->GenSlidingWindowDeclRef() << ";\n"; + ss << code; + ss << " }\n"; + } + } +} + +void SlidingFunctionBase::GenerateRangeArgs( SubArguments& vSubArguments, + outputstream& ss, const char* code ) +{ + GenerateRangeArgs( 0, vSubArguments.size() - 1, vSubArguments, ss, code ); +} + void SlidingFunctionBase::GenerateFunctionDeclaration( const std::string& sSymName, SubArguments& vSubArguments, outputstream& ss ) { diff --git a/sc/source/core/opencl/opbase.hxx b/sc/source/core/opencl/opbase.hxx index 370cbcf2bba2..dbd19e7425ca 100644 --- a/sc/source/core/opencl/opbase.hxx +++ b/sc/source/core/opencl/opbase.hxx @@ -254,7 +254,7 @@ public: virtual void GenSlidingWindowFunction( outputstream&, const std::string&, SubArguments& ) = 0; protected: - // generate code for "double = ;" from vSubArguments + // generate code for "double = ;" from vSubArguments, svDoubleVectorRef is not supported static void GenerateArg( const char* name, int num, SubArguments& vSubArguments, outputstream& ss ); // overload, variable will be named "arg" static void GenerateArg( int num, SubArguments& vSubArguments, outputstream& ss ); @@ -264,6 +264,13 @@ protected: outputstream& ss ); void GenerateFunctionDeclaration( const std::string& sSymName, SubArguments& vSubArguments, outputstream& ss ); + // Generate code that will handle all arguments firstArg-lastArg (zero-based, inclusive), + // including range arguments (svDoubleVectorRef) and each value will be processed by 'code', + // value will be named "arg". There is no isnan(arg) checking. + static void GenerateRangeArgs( int firstArg, int lastArg, SubArguments& vSubArguments, + outputstream& ss, const char* code ); + // overload, handle all arguments + static void GenerateRangeArgs( SubArguments& vSubArguments, outputstream& ss, const char* code ); }; class Normal : public SlidingFunctionBase