summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2015-02-09 16:44:45 +0200
committerTor Lillqvist <tml@collabora.com>2015-02-09 19:38:15 +0200
commitf5e7207053b857b6903a0ab9c161bed9ad7bcee9 (patch)
tree7f245d8be9738d62c69174b91e179717bf67a4ac
parent052fa9bc383f6dd0b6ca705984d03d4ec8d11824 (diff)
Handle zero and empty cells (which also means zero) in OpenCL for division
Not sure if it makes sense to keep having OpDiv a subclass of Reduction. There is no DIV() function that would take a range of cells, so it isn't really comparable to the other Reducion subclasses. But let's keep that as it is for now. We need to handle three cases specially in the OpenCL: Dividing by an empty cell which should produce an #DIV/0! error, dividing an empty cell by zero which also should produce #DIV/0!, and dividing an empty cell with anything else number which should produce 0. Change-Id: I86d86f652047d6f9e3c095c3ef135a8f5396b000
-rw-r--r--sc/source/core/opencl/formulagroupcl.cxx56
1 files changed, 47 insertions, 9 deletions
diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx
index df5659103a5a..b1fb0b175d26 100644
--- a/sc/source/core/opencl/formulagroupcl.cxx
+++ b/sc/source/core/opencl/formulagroupcl.cxx
@@ -1661,6 +1661,11 @@ public:
typedef DynamicKernelSlidingArgument<DynamicKernelStringArgument> StringRange;
typedef ParallelReductionVectorRef<VectorRef> ParallelNumericRange;
+ virtual bool HandleNaNArgument( std::stringstream&, unsigned, SubArguments& ) const
+ {
+ return false;
+ }
+
virtual void GenSlidingWindowFunction( std::stringstream& ss,
const std::string& sSymName, SubArguments& vSubArguments ) SAL_OVERRIDE
{
@@ -1724,18 +1729,25 @@ public:
}
if (ocPush == vSubArguments[i]->GetFormulaToken()->GetOpCode())
{
+ bool bNanHandled = HandleNaNArgument(ss, i, vSubArguments);
+
ss << "tmpBottom = " << GetBottom() << ";\n";
- ss << "if (isNan(";
- ss << vSubArguments[i]->GenSlidingWindowDeclRef();
- ss << "))\n";
- if (ZeroReturnZero())
- ss << " return 0;\n";
- else
+
+ if (!bNanHandled)
{
- ss << " tmp = ";
- ss << Gen2("tmpBottom", "tmp") << ";\n";
+ 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 << "else{\n";
+ ss << "{";
ss << " tmp = ";
ss << Gen2(vSubArguments[i]->GenSlidingWindowDeclRef(), "tmp");
ss << ";\n";
@@ -2147,6 +2159,32 @@ public:
return "(" + rhs + "==0 ? CreateDoubleError(errDivisionByZero) : (" + lhs + "/" + rhs + ") )";
}
virtual std::string BinFuncName() const SAL_OVERRIDE { return "fdiv"; }
+
+ virtual bool HandleNaNArgument( std::stringstream& ss, unsigned argno, SubArguments& vSubArguments ) const SAL_OVERRIDE
+ {
+ if (argno == 1)
+ {
+ ss <<
+ "if (isnan(" << vSubArguments[argno]->GetName() << "[gid0])) {\n"
+ " if (GetDoubleErrorValue(" << vSubArguments[argno]->GetName() << "[gid0]) == errNoValue)\n"
+ " return CreateDoubleError(errDivisionByZero);\n"
+ "}\n";
+ return true;
+ }
+ else if (argno == 0)
+ {
+ ss <<
+ "if (isnan(" << vSubArguments[argno]->GetName() << "[gid0])) {\n"
+ " if (GetDoubleErrorValue(" << vSubArguments[argno]->GetName() << "[gid0]) == errNoValue) {\n"
+ " if (" << vSubArguments[1]->GetName() << "[gid0] == 0)\n"
+ " return CreateDoubleError(errDivisionByZero);\n"
+ " return 0;\n"
+ " }\n"
+ "}\n";
+ }
+ return false;
+ }
+
};
class OpMin : public Reduction