fix and simplify openCL *A functions (COUNTA,MINA, etc.)
These work just like their non-A counterparts, they just also accept strings and treat them as zeros. So instead of having a duplicated function for everything, use the basic functions, detect that string arguments should be treated this way and then convert them in the input data. This as a side-effect also makes the ScCalcConfig::StringConversion::ZERO part work (no idea if that's even been used). Change-Id: I3385b5363c15b0ae45ff191df00ac357e80bd3c6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140226 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
This commit is contained in:
@@ -108,6 +108,7 @@ OUString LimitedString( const OUString& str )
|
||||
return OUString::Concat("\"") + str.subView( 0, 20 ) + "\"...";
|
||||
}
|
||||
|
||||
const int MAX_PEEK_ELEMENTS = 5;
|
||||
// Returns formatted contents of the data (possibly shortened), to be used in debug output.
|
||||
std::string DebugPeekData(const FormulaToken* ref, int doubleRefIndex = 0)
|
||||
{
|
||||
@@ -117,16 +118,19 @@ std::string DebugPeekData(const FormulaToken* ref, int doubleRefIndex = 0)
|
||||
static_cast<const formula::SingleVectorRefToken*>(ref);
|
||||
outputstream buf;
|
||||
buf << "SingleRef {";
|
||||
for( size_t i = 0; i < std::min< size_t >( 4, pSVR->GetArrayLength()); ++i )
|
||||
for( size_t i = 0; i < std::min< size_t >( MAX_PEEK_ELEMENTS, pSVR->GetArrayLength()); ++i )
|
||||
{
|
||||
if( i != 0 )
|
||||
buf << ",";
|
||||
if( pSVR->GetArray().mpNumericArray != nullptr )
|
||||
buf << pSVR->GetArray().mpNumericArray[ i ];
|
||||
else if( pSVR->GetArray().mpStringArray != nullptr )
|
||||
if( pSVR->GetArray().mpStringArray != nullptr
|
||||
&& pSVR->GetArray().mpStringArray[ i ] != nullptr )
|
||||
{
|
||||
buf << LimitedString( OUString( pSVR->GetArray().mpStringArray[ i ] ));
|
||||
}
|
||||
else if( pSVR->GetArray().mpNumericArray != nullptr )
|
||||
buf << pSVR->GetArray().mpNumericArray[ i ];
|
||||
}
|
||||
if( pSVR->GetArrayLength() > 4 )
|
||||
if( pSVR->GetArrayLength() > MAX_PEEK_ELEMENTS )
|
||||
buf << ",...";
|
||||
buf << "}";
|
||||
return buf.str();
|
||||
@@ -137,16 +141,19 @@ std::string DebugPeekData(const FormulaToken* ref, int doubleRefIndex = 0)
|
||||
static_cast<const formula::DoubleVectorRefToken*>(ref);
|
||||
outputstream buf;
|
||||
buf << "DoubleRef {";
|
||||
for( size_t i = 0; i < std::min< size_t >( 4, pDVR->GetArrayLength()); ++i )
|
||||
for( size_t i = 0; i < std::min< size_t >( MAX_PEEK_ELEMENTS, pDVR->GetArrayLength()); ++i )
|
||||
{
|
||||
if( i != 0 )
|
||||
buf << ",";
|
||||
if( pDVR->GetArrays()[doubleRefIndex].mpNumericArray != nullptr )
|
||||
buf << pDVR->GetArrays()[doubleRefIndex].mpNumericArray[ i ];
|
||||
else if( pDVR->GetArrays()[doubleRefIndex].mpStringArray != nullptr )
|
||||
if( pDVR->GetArrays()[doubleRefIndex].mpStringArray != nullptr
|
||||
&& pDVR->GetArrays()[doubleRefIndex].mpStringArray[ i ] != nullptr )
|
||||
{
|
||||
buf << LimitedString( OUString( pDVR->GetArrays()[doubleRefIndex].mpStringArray[ i ] ));
|
||||
}
|
||||
else if( pDVR->GetArrays()[doubleRefIndex].mpNumericArray != nullptr )
|
||||
buf << pDVR->GetArrays()[doubleRefIndex].mpNumericArray[ i ];
|
||||
}
|
||||
if( pDVR->GetArrayLength() > 4 )
|
||||
if( pDVR->GetArrayLength() > MAX_PEEK_ELEMENTS )
|
||||
buf << ",...";
|
||||
buf << "}";
|
||||
return buf.str();
|
||||
@@ -172,13 +179,13 @@ std::string DebugPeekDoubles(const double* data, int size)
|
||||
{
|
||||
outputstream buf;
|
||||
buf << "{";
|
||||
for( int i = 0; i < std::min( 4, size ); ++i )
|
||||
for( int i = 0; i < std::min( MAX_PEEK_ELEMENTS, size ); ++i )
|
||||
{
|
||||
if( i != 0 )
|
||||
buf << ",";
|
||||
buf << data[ i ];
|
||||
}
|
||||
if( size > 4 )
|
||||
if( size > MAX_PEEK_ELEMENTS )
|
||||
buf << ",...";
|
||||
buf << "}";
|
||||
return buf.str();
|
||||
@@ -200,7 +207,21 @@ size_t VectorRef::Marshal( cl_kernel k, int argno, int, cl_program )
|
||||
|
||||
SAL_INFO("sc.opencl", "SingleVectorRef len=" << pSVR->GetArrayLength() << " mpNumericArray=" << pSVR->GetArray().mpNumericArray << " (mpStringArray=" << pSVR->GetArray().mpStringArray << ")");
|
||||
|
||||
pHostBuffer = const_cast<double*>(pSVR->GetArray().mpNumericArray);
|
||||
if( forceStringsToZero && pSVR->GetArray().mpStringArray != nullptr )
|
||||
{
|
||||
dataBuffer.resize( pSVR->GetArrayLength());
|
||||
for( size_t i = 0; i < pSVR->GetArrayLength(); ++i )
|
||||
if( pSVR->GetArray().mpStringArray[ i ] != nullptr )
|
||||
dataBuffer[ i ] = 0;
|
||||
else
|
||||
dataBuffer[ i ] = pSVR->GetArray().mpNumericArray[ i ];
|
||||
pHostBuffer = dataBuffer.data();
|
||||
SAL_INFO("sc.opencl", "Forced strings to zero : " << DebugPeekDoubles( pHostBuffer, pSVR->GetArrayLength()));
|
||||
}
|
||||
else
|
||||
{
|
||||
pHostBuffer = const_cast<double*>(pSVR->GetArray().mpNumericArray);
|
||||
}
|
||||
szHostBuffer = pSVR->GetArrayLength() * sizeof(double);
|
||||
}
|
||||
else if (ref->GetType() == formula::svDoubleVectorRef)
|
||||
@@ -210,8 +231,21 @@ size_t VectorRef::Marshal( cl_kernel k, int argno, int, cl_program )
|
||||
|
||||
SAL_INFO("sc.opencl", "DoubleVectorRef index=" << mnIndex << " len=" << pDVR->GetArrayLength() << " mpNumericArray=" << pDVR->GetArrays()[mnIndex].mpNumericArray << " (mpStringArray=" << pDVR->GetArrays()[mnIndex].mpStringArray << ")");
|
||||
|
||||
pHostBuffer = const_cast<double*>(
|
||||
pDVR->GetArrays()[mnIndex].mpNumericArray);
|
||||
if( forceStringsToZero && pDVR->GetArrays()[mnIndex].mpStringArray != nullptr )
|
||||
{
|
||||
dataBuffer.resize( pDVR->GetArrayLength());
|
||||
for( size_t i = 0; i < pDVR->GetArrayLength(); ++i )
|
||||
if( pDVR->GetArrays()[mnIndex].mpStringArray[ i ] != nullptr )
|
||||
dataBuffer[ i ] = 0;
|
||||
else
|
||||
dataBuffer[ i ] = pDVR->GetArrays()[mnIndex].mpNumericArray[ i ];
|
||||
pHostBuffer = dataBuffer.data();
|
||||
SAL_INFO("sc.opencl", "Forced strings to zero : " << DebugPeekDoubles( pHostBuffer, pDVR->GetArrayLength()));
|
||||
}
|
||||
else
|
||||
{
|
||||
pHostBuffer = const_cast<double*>(pDVR->GetArrays()[mnIndex].mpNumericArray);
|
||||
}
|
||||
szHostBuffer = pDVR->GetArrayLength() * sizeof(double);
|
||||
}
|
||||
else
|
||||
@@ -333,57 +367,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// Arguments that are actually compile-time constants
|
||||
class DynamicKernelConstantArgument : public DynamicKernelArgument
|
||||
{
|
||||
public:
|
||||
DynamicKernelConstantArgument( const ScCalcConfig& config, const std::string& s,
|
||||
const FormulaTreeNodeRef& ft ) :
|
||||
DynamicKernelArgument(config, s, ft) { }
|
||||
/// Generate declaration
|
||||
virtual void GenDecl( outputstream& ss ) const override
|
||||
{
|
||||
ss << "double " << mSymName;
|
||||
}
|
||||
virtual void GenDeclRef( outputstream& ss ) const override
|
||||
{
|
||||
ss << mSymName;
|
||||
}
|
||||
virtual void GenSlidingWindowDecl( outputstream& ss ) const override
|
||||
{
|
||||
GenDecl(ss);
|
||||
}
|
||||
virtual std::string GenSlidingWindowDeclRef( bool = false ) const override
|
||||
{
|
||||
if (GetFormulaToken()->GetType() != formula::svDouble)
|
||||
throw Unhandled(__FILE__, __LINE__);
|
||||
return mSymName;
|
||||
}
|
||||
virtual size_t GetWindowSize() const override
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
double GetDouble() const
|
||||
{
|
||||
FormulaToken* Tok = GetFormulaToken();
|
||||
if (Tok->GetType() != formula::svDouble)
|
||||
throw Unhandled(__FILE__, __LINE__);
|
||||
return Tok->GetDouble();
|
||||
}
|
||||
/// Create buffer and pass the buffer to a given kernel
|
||||
virtual size_t Marshal( cl_kernel k, int argno, int, cl_program ) override
|
||||
{
|
||||
OpenCLZone zone;
|
||||
double tmp = GetDouble();
|
||||
// Pass the scalar result back to the rest of the formula kernel
|
||||
SAL_INFO("sc.opencl", "Kernel " << k << " arg " << argno << ": double: " << preciseFloat( tmp ));
|
||||
cl_int err = clSetKernelArg(k, argno, sizeof(double), static_cast<void*>(&tmp));
|
||||
if (CL_SUCCESS != err)
|
||||
throw OpenCLError("clSetKernelArg", err, __FILE__, __LINE__);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
class DynamicKernelPiArgument : public DynamicKernelArgument
|
||||
{
|
||||
public:
|
||||
@@ -1109,6 +1092,7 @@ size_t DynamicKernelSlidingArgument<Base>::GenReductionLoopHeader( outputstream&
|
||||
}
|
||||
|
||||
template class DynamicKernelSlidingArgument<VectorRef>;
|
||||
template class DynamicKernelSlidingArgument<VectorRefStringsToZero>;
|
||||
template class DynamicKernelSlidingArgument<DynamicKernelStringArgument>;
|
||||
|
||||
namespace {
|
||||
@@ -2070,26 +2054,38 @@ DynamicKernelSoPArguments::DynamicKernelSoPArguments(const ScCalcConfig& config,
|
||||
}
|
||||
else if (pDVR->GetArrays()[j].mpNumericArray &&
|
||||
pCodeGen->takeNumeric() &&
|
||||
(AllStringsAreNull(pDVR->GetArrays()[j].mpStringArray, pDVR->GetArrayLength()) || mCalcConfig.meStringConversion == ScCalcConfig::StringConversion::ZERO))
|
||||
(AllStringsAreNull(pDVR->GetArrays()[j].mpStringArray, pDVR->GetArrayLength())
|
||||
|| mCalcConfig.meStringConversion == ScCalcConfig::StringConversion::ZERO
|
||||
|| pCodeGen->forceStringsToZero()))
|
||||
{
|
||||
// Function takes numbers, and either there
|
||||
// are no strings, or there are strings but
|
||||
// they are to be treated as zero
|
||||
SAL_INFO("sc.opencl", "Numbers (no strings or strings treated as zero)");
|
||||
mvSubArguments.push_back(
|
||||
VectorRefFactory<VectorRef>(mCalcConfig,
|
||||
ts, ft->Children[i], mpCodeGen, j));
|
||||
if(!AllStringsAreNull(pDVR->GetArrays()[j].mpStringArray, pDVR->GetArrayLength()))
|
||||
{
|
||||
mvSubArguments.push_back(
|
||||
VectorRefFactory<VectorRefStringsToZero>(mCalcConfig,
|
||||
ts, ft->Children[i], mpCodeGen, j));
|
||||
}
|
||||
else
|
||||
{
|
||||
mvSubArguments.push_back(
|
||||
VectorRefFactory<VectorRef>(mCalcConfig,
|
||||
ts, ft->Children[i], mpCodeGen, j));
|
||||
}
|
||||
}
|
||||
else if (pDVR->GetArrays()[j].mpNumericArray == nullptr &&
|
||||
pCodeGen->takeNumeric() &&
|
||||
pDVR->GetArrays()[j].mpStringArray &&
|
||||
mCalcConfig.meStringConversion == ScCalcConfig::StringConversion::ZERO)
|
||||
( mCalcConfig.meStringConversion == ScCalcConfig::StringConversion::ZERO
|
||||
|| pCodeGen->forceStringsToZero()))
|
||||
{
|
||||
// Function takes numbers, and there are only
|
||||
// strings, but they are to be treated as zero
|
||||
SAL_INFO("sc.opencl", "Only strings even if want numbers but should be treated as zero");
|
||||
mvSubArguments.push_back(
|
||||
VectorRefFactory<VectorRef>(mCalcConfig,
|
||||
VectorRefFactory<VectorRefStringsToZero>(mCalcConfig,
|
||||
ts, ft->Children[i], mpCodeGen, j));
|
||||
}
|
||||
else if (pDVR->GetArrays()[j].mpStringArray &&
|
||||
@@ -2145,26 +2141,34 @@ DynamicKernelSoPArguments::DynamicKernelSoPArguments(const ScCalcConfig& config,
|
||||
}
|
||||
else if (pSVR->GetArray().mpNumericArray &&
|
||||
pCodeGen->takeNumeric() &&
|
||||
(AllStringsAreNull(pSVR->GetArray().mpStringArray, pSVR->GetArrayLength()) || mCalcConfig.meStringConversion == ScCalcConfig::StringConversion::ZERO))
|
||||
(AllStringsAreNull(pSVR->GetArray().mpStringArray, pSVR->GetArrayLength())
|
||||
|| mCalcConfig.meStringConversion == ScCalcConfig::StringConversion::ZERO
|
||||
|| pCodeGen->forceStringsToZero()))
|
||||
{
|
||||
// Function takes numbers, and either there
|
||||
// are no strings, or there are strings but
|
||||
// they are to be treated as zero
|
||||
SAL_INFO("sc.opencl", "Numbers (no strings or strings treated as zero)");
|
||||
mvSubArguments.push_back(
|
||||
std::make_shared<VectorRef>(mCalcConfig, ts,
|
||||
ft->Children[i]));
|
||||
if( !AllStringsAreNull(pSVR->GetArray().mpStringArray, pSVR->GetArrayLength()))
|
||||
mvSubArguments.push_back(
|
||||
std::make_shared<VectorRefStringsToZero>(mCalcConfig, ts,
|
||||
ft->Children[i]));
|
||||
else
|
||||
mvSubArguments.push_back(
|
||||
std::make_shared<VectorRef>(mCalcConfig, ts,
|
||||
ft->Children[i]));
|
||||
}
|
||||
else if (pSVR->GetArray().mpNumericArray == nullptr &&
|
||||
pCodeGen->takeNumeric() &&
|
||||
pSVR->GetArray().mpStringArray &&
|
||||
mCalcConfig.meStringConversion == ScCalcConfig::StringConversion::ZERO)
|
||||
(mCalcConfig.meStringConversion == ScCalcConfig::StringConversion::ZERO
|
||||
|| pCodeGen->forceStringsToZero()))
|
||||
{
|
||||
// Function takes numbers, and there are only
|
||||
// strings, but they are to be treated as zero
|
||||
SAL_INFO("sc.opencl", "Only strings even if want numbers but should be treated as zero");
|
||||
mvSubArguments.push_back(
|
||||
std::make_shared<VectorRef>(mCalcConfig, ts,
|
||||
std::make_shared<VectorRefStringsToZero>(mCalcConfig, ts,
|
||||
ft->Children[i]));
|
||||
}
|
||||
else if (pSVR->GetArray().mpStringArray &&
|
||||
@@ -2208,6 +2212,16 @@ DynamicKernelSoPArguments::DynamicKernelSoPArguments(const ScCalcConfig& config,
|
||||
std::make_shared<ConstStringArgument>(mCalcConfig, ts,
|
||||
ft->Children[i]));
|
||||
}
|
||||
else if (pChild->GetType() == formula::svString
|
||||
&& !pCodeGen->takeString()
|
||||
&& pCodeGen->takeNumeric()
|
||||
&& pCodeGen->forceStringsToZero())
|
||||
{
|
||||
SAL_INFO("sc.opencl", "Constant string case, treated as zero");
|
||||
mvSubArguments.push_back(
|
||||
DynamicKernelArgumentRef(new DynamicKernelStringToZeroArgument(mCalcConfig, ts,
|
||||
ft->Children[i])));
|
||||
}
|
||||
else
|
||||
{
|
||||
SAL_INFO("sc.opencl", "Unhandled operand, rejecting for OpenCL");
|
||||
@@ -2230,15 +2244,27 @@ DynamicKernelSoPArguments::DynamicKernelSoPArguments(const ScCalcConfig& config,
|
||||
case ocAverage:
|
||||
mvSubArguments.push_back(SoPHelper(mCalcConfig, ts, ft->Children[i], std::make_shared<OpAverage>(nResultSize), nResultSize));
|
||||
break;
|
||||
case ocAverageA:
|
||||
mvSubArguments.push_back(SoPHelper(mCalcConfig, ts, ft->Children[i], std::make_shared<OpAverageA>(nResultSize), nResultSize));
|
||||
break;
|
||||
case ocMin:
|
||||
mvSubArguments.push_back(SoPHelper(mCalcConfig, ts, ft->Children[i], std::make_shared<OpMin>(nResultSize), nResultSize));
|
||||
break;
|
||||
case ocMinA:
|
||||
mvSubArguments.push_back(SoPHelper(mCalcConfig, ts, ft->Children[i], std::make_shared<OpMinA>(nResultSize), nResultSize));
|
||||
break;
|
||||
case ocMax:
|
||||
mvSubArguments.push_back(SoPHelper(mCalcConfig, ts, ft->Children[i], std::make_shared<OpMax>(nResultSize), nResultSize));
|
||||
break;
|
||||
case ocMaxA:
|
||||
mvSubArguments.push_back(SoPHelper(mCalcConfig, ts, ft->Children[i], std::make_shared<OpMaxA>(nResultSize), nResultSize));
|
||||
break;
|
||||
case ocCount:
|
||||
mvSubArguments.push_back(SoPHelper(mCalcConfig, ts, ft->Children[i], std::make_shared<OpCount>(nResultSize), nResultSize));
|
||||
break;
|
||||
case ocCount2:
|
||||
mvSubArguments.push_back(SoPHelper(mCalcConfig, ts, ft->Children[i], std::make_shared<OpCountA>(nResultSize), nResultSize));
|
||||
break;
|
||||
case ocSumProduct:
|
||||
mvSubArguments.push_back(SoPHelper(mCalcConfig, ts, ft->Children[i], std::make_shared<OpSumProduct>(), nResultSize));
|
||||
break;
|
||||
@@ -2849,22 +2875,6 @@ DynamicKernelSoPArguments::DynamicKernelSoPArguments(const ScCalcConfig& config,
|
||||
mvSubArguments.push_back(SoPHelper(mCalcConfig, ts,
|
||||
ft->Children[i], std::make_shared<OpFact>(), nResultSize));
|
||||
break;
|
||||
case ocMinA:
|
||||
mvSubArguments.push_back(SoPHelper(mCalcConfig, ts,
|
||||
ft->Children[i], std::make_shared<OpMinA>(), nResultSize));
|
||||
break;
|
||||
case ocCount2:
|
||||
mvSubArguments.push_back(SoPHelper(mCalcConfig, ts,
|
||||
ft->Children[i], std::make_shared<OpCountA>(), nResultSize));
|
||||
break;
|
||||
case ocMaxA:
|
||||
mvSubArguments.push_back(SoPHelper(mCalcConfig, ts,
|
||||
ft->Children[i], std::make_shared<OpMaxA>(), nResultSize));
|
||||
break;
|
||||
case ocAverageA:
|
||||
mvSubArguments.push_back(SoPHelper(mCalcConfig, ts,
|
||||
ft->Children[i], std::make_shared<OpAverageA>(), nResultSize));
|
||||
break;
|
||||
case ocVarA:
|
||||
mvSubArguments.push_back(SoPHelper(mCalcConfig, ts,
|
||||
ft->Children[i], std::make_shared<OpVarA>(), nResultSize));
|
||||
|
||||
@@ -1650,102 +1650,6 @@ void SumOfProduct::GenSlidingWindowFunction( outputstream& ss,
|
||||
ss << "}";
|
||||
}
|
||||
|
||||
void Reduction::GenSlidingWindowFunction( outputstream& ss,
|
||||
const std::string& sSymName, SubArguments& vSubArguments )
|
||||
{
|
||||
GenerateFunctionDeclaration( sSymName, vSubArguments, ss );
|
||||
ss << "{\n";
|
||||
ss << "double tmp = " << GetBottom() << ";\n";
|
||||
ss << "int gid0 = get_global_id(0);\n";
|
||||
if (isAverage() || isMinOrMax())
|
||||
ss << "int nCount = 0;\n";
|
||||
ss << "double tmpBottom;\n";
|
||||
unsigned i = vSubArguments.size();
|
||||
while (i--)
|
||||
{
|
||||
if (NumericRange* NR = dynamic_cast<NumericRange*>(vSubArguments[i].get()))
|
||||
{
|
||||
bool needBody;
|
||||
NR->GenReductionLoopHeader(ss, needBody);
|
||||
if (!needBody)
|
||||
continue;
|
||||
}
|
||||
else if (ParallelNumericRange* PNR = dynamic_cast<ParallelNumericRange*>(vSubArguments[i].get()))
|
||||
{
|
||||
//did not handle yet
|
||||
bool bNeedBody = false;
|
||||
PNR->GenReductionLoopHeader(ss, mnResultSize, bNeedBody);
|
||||
if (!bNeedBody)
|
||||
continue;
|
||||
}
|
||||
else if (StringRange* SR = dynamic_cast<StringRange*>(vSubArguments[i].get()))
|
||||
{
|
||||
//did not handle yet
|
||||
bool needBody;
|
||||
SR->GenReductionLoopHeader(ss, needBody);
|
||||
if (!needBody)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
FormulaToken* pCur = vSubArguments[i]->GetFormulaToken();
|
||||
assert(pCur);
|
||||
assert(pCur->GetType() != formula::svDoubleVectorRef);
|
||||
|
||||
if (pCur->GetType() == formula::svSingleVectorRef ||
|
||||
pCur->GetType() == formula::svDouble)
|
||||
{
|
||||
ss << "{\n";
|
||||
}
|
||||
}
|
||||
if (ocPush == vSubArguments[i]->GetFormulaToken()->GetOpCode())
|
||||
{
|
||||
bool bNanHandled = HandleNaNArgument(ss, i, vSubArguments);
|
||||
|
||||
ss << "tmpBottom = " << GetBottom() << ";\n";
|
||||
|
||||
if (!bNanHandled)
|
||||
{
|
||||
ss << "if (isnan(";
|
||||
ss << vSubArguments[i]->GenSlidingWindowDeclRef();
|
||||
ss << "))\n";
|
||||
if (ZeroReturnZero())
|
||||
ss << " return 0;\n";
|
||||
else
|
||||
{
|
||||
ss << " tmp = ";
|
||||
ss << Gen2("tmpBottom", "tmp") << ";\n";
|
||||
}
|
||||
ss << "else\n";
|
||||
}
|
||||
ss << "{";
|
||||
ss << " tmp = ";
|
||||
ss << Gen2(vSubArguments[i]->GenSlidingWindowDeclRef(), "tmp");
|
||||
ss << ";\n";
|
||||
ss << " }\n";
|
||||
ss << "}\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
ss << "tmp = ";
|
||||
ss << Gen2(vSubArguments[i]->GenSlidingWindowDeclRef(), "tmp");
|
||||
ss << ";\n";
|
||||
}
|
||||
}
|
||||
if (isAverage())
|
||||
ss <<
|
||||
"if (nCount==0)\n"
|
||||
" return CreateDoubleError(DivisionByZero);\n";
|
||||
else if (isMinOrMax())
|
||||
ss <<
|
||||
"if (nCount==0)\n"
|
||||
" return 0;\n";
|
||||
ss << "return tmp";
|
||||
if (isAverage())
|
||||
ss << "/(double)nCount";
|
||||
ss << ";\n}";
|
||||
}
|
||||
|
||||
void OpSum::BinInlineFun(std::set<std::string>& decls,std::set<std::string>& funs)
|
||||
{
|
||||
decls.insert(is_representable_integerDecl);
|
||||
@@ -1756,12 +1660,6 @@ void OpSum::BinInlineFun(std::set<std::string>& decls,std::set<std::string>& fun
|
||||
funs.insert(fsum_approx);
|
||||
}
|
||||
|
||||
void OpAverage::BinInlineFun(std::set<std::string>& decls,std::set<std::string>& funs)
|
||||
{
|
||||
decls.insert(fsum_countDecl);
|
||||
funs.insert(fsum_count);
|
||||
}
|
||||
|
||||
void OpSub::BinInlineFun(std::set<std::string>& decls,std::set<std::string>& funs)
|
||||
{
|
||||
decls.insert(is_representable_integerDecl);
|
||||
@@ -1772,18 +1670,6 @@ void OpSub::BinInlineFun(std::set<std::string>& decls,std::set<std::string>& fun
|
||||
funs.insert(fsub_approx);
|
||||
}
|
||||
|
||||
void OpMin::BinInlineFun(std::set<std::string>& decls,std::set<std::string>& funs)
|
||||
{
|
||||
decls.insert(fmin_countDecl);
|
||||
funs.insert(fmin_count);
|
||||
}
|
||||
|
||||
void OpMax::BinInlineFun(std::set<std::string>& decls,std::set<std::string>& funs)
|
||||
{
|
||||
decls.insert(fmax_countDecl);
|
||||
funs.insert(fmax_count);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
@@ -570,29 +570,6 @@ public:
|
||||
virtual std::string BinFuncName() const override { return "fsop"; }
|
||||
};
|
||||
|
||||
class Reduction : public SlidingFunctionBase
|
||||
{
|
||||
int const mnResultSize;
|
||||
public:
|
||||
explicit Reduction(int nResultSize) : mnResultSize(nResultSize) {}
|
||||
|
||||
typedef DynamicKernelSlidingArgument<VectorRef> NumericRange;
|
||||
typedef DynamicKernelSlidingArgument<DynamicKernelStringArgument> StringRange;
|
||||
typedef ParallelReductionVectorRef<VectorRef> ParallelNumericRange;
|
||||
|
||||
virtual bool HandleNaNArgument( outputstream&, unsigned, SubArguments& ) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void GenSlidingWindowFunction( outputstream& ss,
|
||||
const std::string& sSymName, SubArguments& vSubArguments ) override;
|
||||
virtual bool isAverage() const { return false; }
|
||||
virtual bool isMinOrMax() const { return false; }
|
||||
virtual bool takeString() const override { return false; }
|
||||
virtual bool takeNumeric() const override { return true; }
|
||||
};
|
||||
|
||||
/// operator traits
|
||||
class OpNop : public Reduction
|
||||
{
|
||||
@@ -607,22 +584,6 @@ public:
|
||||
virtual std::string BinFuncName() const override { return "nop"; }
|
||||
};
|
||||
|
||||
class OpCount : public Reduction
|
||||
{
|
||||
public:
|
||||
explicit OpCount(int nResultSize) : Reduction(nResultSize) {}
|
||||
|
||||
virtual std::string GetBottom() override { return "0"; }
|
||||
virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) const override
|
||||
{
|
||||
outputstream ss;
|
||||
ss << "(isnan(" << lhs << ")?" << rhs << ":" << rhs << "+1.0)";
|
||||
return ss.str();
|
||||
}
|
||||
virtual std::string BinFuncName() const override { return "fcount"; }
|
||||
virtual bool canHandleMultiVector() const override { return true; }
|
||||
};
|
||||
|
||||
class OpSum : public Reduction
|
||||
{
|
||||
public:
|
||||
@@ -641,24 +602,6 @@ public:
|
||||
virtual bool canHandleMultiVector() const override { return true; }
|
||||
};
|
||||
|
||||
class OpAverage : public Reduction
|
||||
{
|
||||
public:
|
||||
explicit OpAverage(int nResultSize) : Reduction(nResultSize) {}
|
||||
|
||||
virtual std::string GetBottom() override { return "0"; }
|
||||
virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) const override
|
||||
{
|
||||
outputstream ss;
|
||||
ss << "fsum_count(" << lhs << "," << rhs << ", &nCount)";
|
||||
return ss.str();
|
||||
}
|
||||
virtual void BinInlineFun(std::set<std::string>& decls,std::set<std::string>& funs) override;
|
||||
virtual std::string BinFuncName() const override { return "average"; }
|
||||
virtual bool isAverage() const override { return true; }
|
||||
virtual bool canHandleMultiVector() const override { return true; }
|
||||
};
|
||||
|
||||
class OpSub : public Reduction
|
||||
{
|
||||
public:
|
||||
@@ -723,39 +666,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
class OpMin : public Reduction
|
||||
{
|
||||
public:
|
||||
explicit OpMin(int nResultSize) : Reduction(nResultSize) {}
|
||||
|
||||
virtual std::string GetBottom() override { return "NAN"; }
|
||||
virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) const override
|
||||
{
|
||||
return "fmin_count(" + lhs + "," + rhs + ", &nCount)";
|
||||
}
|
||||
virtual void BinInlineFun(std::set<std::string>& decls,std::set<std::string>& funs) override;
|
||||
virtual std::string BinFuncName() const override { return "min"; }
|
||||
virtual bool isMinOrMax() const override { return true; }
|
||||
virtual bool canHandleMultiVector() const override { return true; }
|
||||
};
|
||||
|
||||
class OpMax : public Reduction
|
||||
{
|
||||
public:
|
||||
explicit OpMax(int nResultSize) : Reduction(nResultSize) {}
|
||||
|
||||
virtual std::string GetBottom() override { return "NAN"; }
|
||||
virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) const override
|
||||
{
|
||||
return "fmax_count(" + lhs + "," + rhs + ", &nCount)";
|
||||
}
|
||||
virtual void BinInlineFun(std::set<std::string>& decls,std::set<std::string>& funs) override;
|
||||
virtual std::string BinFuncName() const override { return "max"; }
|
||||
virtual bool isMinOrMax() const override { return true; }
|
||||
virtual bool canHandleMultiVector() const override { return true; }
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
@@ -86,32 +86,6 @@ const char atan2Content[] =
|
||||
" return a;\n"
|
||||
"}\n";
|
||||
|
||||
const char fsum_countDecl[] = "double fsum_count(double a, double b, __private int *p);\n";
|
||||
const char fsum_count[] =
|
||||
"double fsum_count(double a, double b, __private int *p) {\n"
|
||||
" bool t = isnan(a);\n"
|
||||
" (*p) += t?0:1;\n"
|
||||
" return t?b:a+b;\n"
|
||||
"}\n";
|
||||
|
||||
const char fmin_countDecl[] = "double fmin_count(double a, double b, __private int *p);\n";
|
||||
const char fmin_count[] =
|
||||
"double fmin_count(double a, double b, __private int *p) {\n"
|
||||
" double result = fmin(a, b);\n"
|
||||
" bool t = isnan(result);\n"
|
||||
" (*p) += t?0:1;\n"
|
||||
" return result;\n"
|
||||
"}\n";
|
||||
|
||||
const char fmax_countDecl[] = "double fmax_count(double a, double b, __private int *p);\n";
|
||||
const char fmax_count[] =
|
||||
"double fmax_count(double a, double b, __private int *p) {\n"
|
||||
" double result = fmax(a, b);\n"
|
||||
" bool t = isnan(result);\n"
|
||||
" (*p) += t?0:1;\n"
|
||||
" return result;\n"
|
||||
"}\n";
|
||||
|
||||
const char is_representable_integerDecl[] = "int is_representable_integer(double a);\n";
|
||||
const char is_representable_integer[] =
|
||||
"int is_representable_integer(double a) {\n"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -503,83 +503,123 @@ public:
|
||||
virtual std::string BinFuncName() const override { return "OpRsq"; }
|
||||
};
|
||||
|
||||
class OpMinA: public Normal
|
||||
class OpMin : public Reduction
|
||||
{
|
||||
public:
|
||||
virtual void GenSlidingWindowFunction(outputstream &ss,
|
||||
const std::string &sSymName, SubArguments &vSubArguments) override;
|
||||
virtual std::string BinFuncName() const override { return "OpMinA"; }
|
||||
virtual bool takeString() const override { return true; }
|
||||
virtual bool takeNumeric() const override { return true; }
|
||||
explicit OpMin(int nResultSize) : Reduction(nResultSize) {}
|
||||
|
||||
virtual std::string GetBottom() override { return "NAN"; }
|
||||
virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) const override
|
||||
{
|
||||
return "fmin_count(" + lhs + "," + rhs + ", &nCount)";
|
||||
}
|
||||
virtual void BinInlineFun(std::set<std::string>& decls,std::set<std::string>& funs) override;
|
||||
virtual std::string BinFuncName() const override { return "min"; }
|
||||
virtual bool isMinOrMax() const override { return true; }
|
||||
virtual bool canHandleMultiVector() const override { return true; }
|
||||
};
|
||||
class OpCountA: public Normal
|
||||
|
||||
class OpMax : public Reduction
|
||||
{
|
||||
public:
|
||||
virtual void GenSlidingWindowFunction(outputstream &ss,
|
||||
const std::string &sSymName, SubArguments &vSubArguments) override;
|
||||
explicit OpMax(int nResultSize) : Reduction(nResultSize) {}
|
||||
|
||||
virtual std::string GetBottom() override { return "NAN"; }
|
||||
virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) const override
|
||||
{
|
||||
return "fmax_count(" + lhs + "," + rhs + ", &nCount)";
|
||||
}
|
||||
virtual void BinInlineFun(std::set<std::string>& decls,std::set<std::string>& funs) override;
|
||||
virtual std::string BinFuncName() const override { return "max"; }
|
||||
virtual bool isMinOrMax() const override { return true; }
|
||||
virtual bool canHandleMultiVector() const override { return true; }
|
||||
};
|
||||
|
||||
class OpAverage : public Reduction
|
||||
{
|
||||
public:
|
||||
explicit OpAverage(int nResultSize) : Reduction(nResultSize) {}
|
||||
|
||||
virtual std::string GetBottom() override { return "0"; }
|
||||
virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) const override
|
||||
{
|
||||
outputstream ss;
|
||||
ss << "fsum_count(" << lhs << "," << rhs << ", &nCount)";
|
||||
return ss.str();
|
||||
}
|
||||
virtual void BinInlineFun(std::set<std::string>& decls,std::set<std::string>& funs) override;
|
||||
virtual std::string BinFuncName() const override { return "average"; }
|
||||
virtual bool isAverage() const override { return true; }
|
||||
virtual bool canHandleMultiVector() const override { return true; }
|
||||
};
|
||||
|
||||
class OpCount : public Reduction
|
||||
{
|
||||
public:
|
||||
explicit OpCount(int nResultSize) : Reduction(nResultSize) {}
|
||||
|
||||
virtual std::string GetBottom() override { return "0"; }
|
||||
virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) const override
|
||||
{
|
||||
outputstream ss;
|
||||
ss << "(isnan(" << lhs << ")?" << rhs << ":" << rhs << "+1.0)";
|
||||
return ss.str();
|
||||
}
|
||||
virtual std::string BinFuncName() const override { return "fcount"; }
|
||||
virtual bool canHandleMultiVector() const override { return true; }
|
||||
};
|
||||
|
||||
class OpCountA: public OpCount
|
||||
{
|
||||
public:
|
||||
explicit OpCountA(int nResultSize) : OpCount(nResultSize) {}
|
||||
virtual std::string BinFuncName() const override { return "OpCountA"; }
|
||||
virtual bool takeString() const override { return true; }
|
||||
virtual bool takeNumeric() const override { return true; }
|
||||
virtual bool canHandleMultiVector() const override { return true; }
|
||||
virtual bool forceStringsToZero() const override { return true; }
|
||||
};
|
||||
class OpMaxA: public Normal
|
||||
class OpMaxA: public OpMax
|
||||
{
|
||||
public:
|
||||
virtual void GenSlidingWindowFunction(outputstream &ss,
|
||||
const std::string &sSymName, SubArguments &vSubArguments) override;
|
||||
explicit OpMaxA(int nResultSize) : OpMax(nResultSize) {}
|
||||
virtual std::string BinFuncName() const override { return "OpMaxA"; }
|
||||
virtual bool takeString() const override { return true; }
|
||||
virtual bool takeNumeric() const override { return true; }
|
||||
virtual bool canHandleMultiVector() const override { return true; }
|
||||
virtual bool forceStringsToZero() const override { return true; }
|
||||
};
|
||||
class OpVarA: public Normal
|
||||
class OpMinA : public OpMin
|
||||
{
|
||||
public:
|
||||
explicit OpMinA(int nResultSize) : OpMin(nResultSize) {}
|
||||
virtual std::string BinFuncName() const override { return "OpMinA"; }
|
||||
virtual bool forceStringsToZero() const override { return true; }
|
||||
};
|
||||
class OpVarA: public OpVar
|
||||
{
|
||||
public:
|
||||
virtual void GenSlidingWindowFunction(outputstream &ss,
|
||||
const std::string &sSymName, SubArguments &vSubArguments) override;
|
||||
virtual std::string BinFuncName() const override { return "OpVarA"; }
|
||||
virtual bool takeString() const override { return true; }
|
||||
virtual bool takeNumeric() const override { return true; }
|
||||
virtual bool canHandleMultiVector() const override { return true; }
|
||||
virtual bool forceStringsToZero() const override { return true; }
|
||||
};
|
||||
class OpVarPA: public Normal
|
||||
class OpVarPA: public OpVarP
|
||||
{
|
||||
public:
|
||||
virtual void GenSlidingWindowFunction(outputstream &ss,
|
||||
const std::string &sSymName, SubArguments &vSubArguments) override;
|
||||
virtual std::string BinFuncName() const override { return "OpVarPA"; }
|
||||
virtual bool takeString() const override { return true; }
|
||||
virtual bool takeNumeric() const override { return true; }
|
||||
virtual bool canHandleMultiVector() const override { return true; }
|
||||
virtual bool forceStringsToZero() const override { return true; }
|
||||
};
|
||||
class OpStDevPA: public Normal
|
||||
class OpStDevPA: public OpStDevP
|
||||
{
|
||||
public:
|
||||
virtual void GenSlidingWindowFunction(outputstream &ss,
|
||||
const std::string &sSymName, SubArguments &vSubArguments) override;
|
||||
virtual std::string BinFuncName() const override { return "OpStDevPA"; }
|
||||
virtual bool takeString() const override { return true; }
|
||||
virtual bool takeNumeric() const override { return true; }
|
||||
virtual bool forceStringsToZero() const override { return true; }
|
||||
};
|
||||
class OpAverageA: public Normal
|
||||
class OpAverageA: public OpAverage
|
||||
{
|
||||
public:
|
||||
virtual void GenSlidingWindowFunction(outputstream &ss,
|
||||
const std::string &sSymName, SubArguments &vSubArguments) override;
|
||||
explicit OpAverageA(int nResultSize) : OpAverage(nResultSize) {}
|
||||
virtual std::string BinFuncName() const override { return "OpAverageA"; }
|
||||
virtual bool takeString() const override { return true; }
|
||||
virtual bool takeNumeric() const override { return true; }
|
||||
virtual bool canHandleMultiVector() const override { return true; }
|
||||
virtual bool forceStringsToZero() const override { return true; }
|
||||
};
|
||||
class OpStDevA: public Normal
|
||||
class OpStDevA: public OpStDev
|
||||
{
|
||||
public:
|
||||
virtual void GenSlidingWindowFunction(outputstream &ss,
|
||||
const std::string &sSymName, SubArguments &vSubArguments) override;
|
||||
virtual std::string BinFuncName() const override { return "OpStDevA"; }
|
||||
virtual bool takeString() const override { return true; }
|
||||
virtual bool takeNumeric() const override { return true; }
|
||||
virtual bool forceStringsToZero() const override { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,29 @@ const char GetValue[] =
|
||||
"{\n"
|
||||
" return fp - 2 * GetTDist(x, fDF);\n"
|
||||
"}\n";
|
||||
const char fmin_countDecl[] = "double fmin_count(double a, double b, __private int *p);\n";
|
||||
const char fmin_count[] =
|
||||
"double fmin_count(double a, double b, __private int *p) {\n"
|
||||
" double result = fmin(a, b);\n"
|
||||
" bool t = isnan(result);\n"
|
||||
" (*p) += t?0:1;\n"
|
||||
" return result;\n"
|
||||
"}\n";
|
||||
const char fmax_countDecl[] = "double fmax_count(double a, double b, __private int *p);\n";
|
||||
const char fmax_count[] =
|
||||
"double fmax_count(double a, double b, __private int *p) {\n"
|
||||
" double result = fmax(a, b);\n"
|
||||
" bool t = isnan(result);\n"
|
||||
" (*p) += t?0:1;\n"
|
||||
" return result;\n"
|
||||
"}\n";
|
||||
const char fsum_countDecl[] = "double fsum_count(double a, double b, __private int *p);\n";
|
||||
const char fsum_count[] =
|
||||
"double fsum_count(double a, double b, __private int *p) {\n"
|
||||
" bool t = isnan(a);\n"
|
||||
" (*p) += t?0:1;\n"
|
||||
" return t?b:a+b;\n"
|
||||
"}\n";
|
||||
const char GetGammaSeriesDecl[] =
|
||||
"double GetGammaSeries( double fA, double fX );\n";
|
||||
const char GetGammaSeries[] =
|
||||
|
||||
@@ -84,7 +84,7 @@ bool DynamicKernelArgument::NeedParallelReduction() const
|
||||
}
|
||||
|
||||
VectorRef::VectorRef( const ScCalcConfig& config, const std::string& s, const FormulaTreeNodeRef& ft, int idx ) :
|
||||
DynamicKernelArgument(config, s, ft), mpClmem(nullptr), mnIndex(idx)
|
||||
DynamicKernelArgument(config, s, ft), mpClmem(nullptr), mnIndex(idx), forceStringsToZero( false )
|
||||
{
|
||||
if (mnIndex)
|
||||
{
|
||||
@@ -174,6 +174,13 @@ bool VectorRef::NeedParallelReduction() const
|
||||
return false;
|
||||
}
|
||||
|
||||
VectorRefStringsToZero::VectorRefStringsToZero( const ScCalcConfig& config, const std::string& s,
|
||||
const FormulaTreeNodeRef& ft, int index )
|
||||
: VectorRef( config, s, ft, index )
|
||||
{
|
||||
forceStringsToZero = true;
|
||||
}
|
||||
|
||||
void SlidingFunctionBase::GenerateArg( const char* name, int arg, SubArguments& vSubArguments, outputstream& ss )
|
||||
{
|
||||
assert( arg < int( vSubArguments.size()));
|
||||
@@ -196,6 +203,11 @@ void SlidingFunctionBase::GenerateArg( const char* name, int arg, SubArguments&
|
||||
}
|
||||
else if(token->GetType() == formula::svDouble)
|
||||
ss << " " << name << " = " << token->GetDouble() << ";\n";
|
||||
else if(token->GetType() == formula::svString)
|
||||
{
|
||||
assert( dynamic_cast<DynamicKernelStringToZeroArgument*>(vSubArguments[arg].get()));
|
||||
ss << " " << name << " = 0.0;\n";
|
||||
}
|
||||
else
|
||||
throw Unhandled( __FILE__, __LINE__ );
|
||||
}
|
||||
@@ -259,13 +271,23 @@ void SlidingFunctionBase::GenerateRangeArgs( int firstArg, int lastArg, SubArgum
|
||||
ss << code;
|
||||
ss << " }\n";
|
||||
}
|
||||
else
|
||||
else if(token->GetType() == formula::svDouble)
|
||||
{
|
||||
ss << " {\n";
|
||||
ss << " double arg = " << token->GetDouble() << ";\n";
|
||||
ss << code;
|
||||
ss << " }\n";
|
||||
}
|
||||
else if(token->GetType() == formula::svString)
|
||||
{
|
||||
assert( dynamic_cast<DynamicKernelStringToZeroArgument*>(vSubArguments[i].get()));
|
||||
ss << " {\n";
|
||||
ss << " double arg = 0.0;\n";
|
||||
ss << code;
|
||||
ss << " }\n";
|
||||
}
|
||||
else
|
||||
throw Unhandled( __FILE__, __LINE__ );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -611,6 +633,104 @@ void CheckVariables::UnrollDoubleVector( outputstream& ss,
|
||||
ss << " }\n";
|
||||
}
|
||||
|
||||
void Reduction::GenSlidingWindowFunction( outputstream& ss,
|
||||
const std::string& sSymName, SubArguments& vSubArguments )
|
||||
{
|
||||
GenerateFunctionDeclaration( sSymName, vSubArguments, ss );
|
||||
ss << "{\n";
|
||||
ss << "double tmp = " << GetBottom() << ";\n";
|
||||
ss << "int gid0 = get_global_id(0);\n";
|
||||
if (isAverage() || isMinOrMax())
|
||||
ss << "int nCount = 0;\n";
|
||||
ss << "double tmpBottom;\n";
|
||||
unsigned i = vSubArguments.size();
|
||||
while (i--)
|
||||
{
|
||||
if (NumericRange* NR = dynamic_cast<NumericRange*>(vSubArguments[i].get()))
|
||||
{
|
||||
bool needBody;
|
||||
NR->GenReductionLoopHeader(ss, needBody);
|
||||
if (!needBody)
|
||||
continue;
|
||||
}
|
||||
else if (NumericRangeStringsToZero* NRS = dynamic_cast<NumericRangeStringsToZero*>(vSubArguments[i].get()))
|
||||
{
|
||||
bool needBody;
|
||||
NRS->GenReductionLoopHeader(ss, needBody);
|
||||
if (!needBody)
|
||||
continue;
|
||||
}
|
||||
else if (ParallelNumericRange* PNR = dynamic_cast<ParallelNumericRange*>(vSubArguments[i].get()))
|
||||
{
|
||||
//did not handle yet
|
||||
bool bNeedBody = false;
|
||||
PNR->GenReductionLoopHeader(ss, mnResultSize, bNeedBody);
|
||||
if (!bNeedBody)
|
||||
continue;
|
||||
}
|
||||
else if (StringRange* SR = dynamic_cast<StringRange*>(vSubArguments[i].get()))
|
||||
{
|
||||
//did not handle yet
|
||||
bool needBody;
|
||||
SR->GenReductionLoopHeader(ss, needBody);
|
||||
if (!needBody)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
FormulaToken* pCur = vSubArguments[i]->GetFormulaToken();
|
||||
if( pCur == nullptr || pCur->GetType() == formula::svDoubleVectorRef )
|
||||
{
|
||||
throw Unhandled(__FILE__, __LINE__);
|
||||
}
|
||||
ss << "{\n";
|
||||
}
|
||||
if (ocPush == vSubArguments[i]->GetFormulaToken()->GetOpCode())
|
||||
{
|
||||
bool bNanHandled = HandleNaNArgument(ss, i, vSubArguments);
|
||||
|
||||
ss << " tmpBottom = " << GetBottom() << ";\n";
|
||||
|
||||
if (!bNanHandled)
|
||||
{
|
||||
ss << " if (isnan(";
|
||||
ss << vSubArguments[i]->GenSlidingWindowDeclRef();
|
||||
ss << "))\n";
|
||||
if (ZeroReturnZero())
|
||||
ss << " return 0;\n";
|
||||
else
|
||||
{
|
||||
ss << " tmp = ";
|
||||
ss << Gen2("tmpBottom", "tmp") << ";\n";
|
||||
}
|
||||
ss << " else\n";
|
||||
}
|
||||
ss << " tmp = ";
|
||||
ss << Gen2(vSubArguments[i]->GenSlidingWindowDeclRef(), "tmp");
|
||||
ss << ";\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
ss << " tmp = ";
|
||||
ss << Gen2(vSubArguments[i]->GenSlidingWindowDeclRef(), "tmp");
|
||||
ss << ";\n";
|
||||
}
|
||||
ss << "}\n";
|
||||
}
|
||||
if (isAverage())
|
||||
ss <<
|
||||
"if (nCount==0)\n"
|
||||
" return CreateDoubleError(DivisionByZero);\n";
|
||||
else if (isMinOrMax())
|
||||
ss <<
|
||||
"if (nCount==0)\n"
|
||||
" return 0;\n";
|
||||
ss << "return tmp";
|
||||
if (isAverage())
|
||||
ss << "/(double)nCount";
|
||||
ss << ";\n}";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <formula/token.hxx>
|
||||
#include <formula/types.hxx>
|
||||
#include <formula/vectortoken.hxx>
|
||||
#include <opencl/OpenCLZone.hxx>
|
||||
#include <sal/log.hxx>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
@@ -94,7 +96,7 @@ public:
|
||||
} while( false )
|
||||
#define CHECK_PARAMETER_DOUBLEVECTORREF(arg) \
|
||||
do { \
|
||||
FormulaToken *token = vSubArguments[arg]->GetFormulaToken(); \
|
||||
formula::FormulaToken *token = vSubArguments[arg]->GetFormulaToken(); \
|
||||
if (token == nullptr || token->GetType() != formula::svDoubleVectorRef) \
|
||||
throw Unhandled(__FILE__, __LINE__); \
|
||||
} while( false )
|
||||
@@ -206,6 +208,17 @@ protected:
|
||||
cl_mem mpClmem;
|
||||
// index in multiple double vector refs that have multiple ranges
|
||||
const int mnIndex;
|
||||
// Makes Marshall convert strings to 0 values.
|
||||
bool forceStringsToZero;
|
||||
// Used for storing when the data needs to be modified before sending to OpenCL.
|
||||
std::vector< double > dataBuffer;
|
||||
};
|
||||
|
||||
// Sets VectorRef::forceStringsToZero.
|
||||
class VectorRefStringsToZero : public VectorRef
|
||||
{
|
||||
public:
|
||||
VectorRefStringsToZero( const ScCalcConfig& config, const std::string& s, const FormulaTreeNodeRef& ft, int index = 0 );
|
||||
};
|
||||
|
||||
/// A vector of strings
|
||||
@@ -229,6 +242,72 @@ public:
|
||||
virtual size_t Marshal( cl_kernel, int, int, cl_program ) override;
|
||||
};
|
||||
|
||||
/// Arguments that are actually compile-time constants
|
||||
class DynamicKernelConstantArgument : public DynamicKernelArgument
|
||||
{
|
||||
public:
|
||||
DynamicKernelConstantArgument( const ScCalcConfig& config, const std::string& s,
|
||||
const FormulaTreeNodeRef& ft ) :
|
||||
DynamicKernelArgument(config, s, ft) { }
|
||||
/// Generate declaration
|
||||
virtual void GenDecl( outputstream& ss ) const override
|
||||
{
|
||||
ss << "double " << mSymName;
|
||||
}
|
||||
virtual void GenDeclRef( outputstream& ss ) const override
|
||||
{
|
||||
ss << mSymName;
|
||||
}
|
||||
virtual void GenSlidingWindowDecl( outputstream& ss ) const override
|
||||
{
|
||||
GenDecl(ss);
|
||||
}
|
||||
virtual std::string GenSlidingWindowDeclRef( bool = false ) const override
|
||||
{
|
||||
if (GetFormulaToken()->GetType() != formula::svDouble)
|
||||
throw Unhandled(__FILE__, __LINE__);
|
||||
return mSymName;
|
||||
}
|
||||
virtual size_t GetWindowSize() const override
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
virtual double GetDouble() const
|
||||
{
|
||||
formula::FormulaToken* Tok = GetFormulaToken();
|
||||
if (Tok->GetType() != formula::svDouble)
|
||||
throw Unhandled(__FILE__, __LINE__);
|
||||
return Tok->GetDouble();
|
||||
}
|
||||
/// Create buffer and pass the buffer to a given kernel
|
||||
virtual size_t Marshal( cl_kernel k, int argno, int, cl_program ) override
|
||||
{
|
||||
OpenCLZone zone;
|
||||
double tmp = GetDouble();
|
||||
// Pass the scalar result back to the rest of the formula kernel
|
||||
SAL_INFO("sc.opencl", "Kernel " << k << " arg " << argno << ": double: " << preciseFloat( tmp ));
|
||||
cl_int err = clSetKernelArg(k, argno, sizeof(double), static_cast<void*>(&tmp));
|
||||
if (CL_SUCCESS != err)
|
||||
throw OpenCLError("clSetKernelArg", err, __FILE__, __LINE__);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
// Constant 0 argument when a string is forced to zero.
|
||||
class DynamicKernelStringToZeroArgument : public DynamicKernelConstantArgument
|
||||
{
|
||||
public:
|
||||
DynamicKernelStringToZeroArgument( const ScCalcConfig& config, const std::string& s,
|
||||
const FormulaTreeNodeRef& ft ) :
|
||||
DynamicKernelConstantArgument(config, s, ft) { }
|
||||
virtual std::string GenSlidingWindowDeclRef( bool = false ) const override
|
||||
{
|
||||
return mSymName;
|
||||
}
|
||||
virtual double GetDouble() const override { return 0; }
|
||||
};
|
||||
|
||||
|
||||
/// Abstract class for code generation
|
||||
class OpBase
|
||||
{
|
||||
@@ -250,6 +329,8 @@ public:
|
||||
//Continue process 'Zero' or Not(like OpMul, not continue process when meet
|
||||
// 'Zero'
|
||||
virtual bool ZeroReturnZero() { return false;}
|
||||
// For use with COUNTA() etc, input strings will be converted to 0 in data.
|
||||
virtual bool forceStringsToZero() const { return false; }
|
||||
virtual ~OpBase() { }
|
||||
};
|
||||
|
||||
@@ -393,6 +474,30 @@ protected:
|
||||
cl_mem mpClmem2;
|
||||
};
|
||||
|
||||
class Reduction : public SlidingFunctionBase
|
||||
{
|
||||
int const mnResultSize;
|
||||
public:
|
||||
explicit Reduction(int nResultSize) : mnResultSize(nResultSize) {}
|
||||
|
||||
typedef DynamicKernelSlidingArgument<VectorRef> NumericRange;
|
||||
typedef DynamicKernelSlidingArgument<VectorRefStringsToZero> NumericRangeStringsToZero;
|
||||
typedef DynamicKernelSlidingArgument<DynamicKernelStringArgument> StringRange;
|
||||
typedef ParallelReductionVectorRef<VectorRef> ParallelNumericRange;
|
||||
|
||||
virtual bool HandleNaNArgument( outputstream&, unsigned, SubArguments& ) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void GenSlidingWindowFunction( outputstream& ss,
|
||||
const std::string& sSymName, SubArguments& vSubArguments ) override;
|
||||
virtual bool isAverage() const { return false; }
|
||||
virtual bool isMinOrMax() const { return false; }
|
||||
virtual bool takeString() const override { return false; }
|
||||
virtual bool takeNumeric() const override { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
Reference in New Issue
Block a user