summaryrefslogtreecommitdiff
path: root/sc/source/core/opencl
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/core/opencl')
-rw-r--r--sc/source/core/opencl/formulagroupcl.cxx58
-rw-r--r--sc/source/core/opencl/formulagroupcl_public.hxx21
2 files changed, 69 insertions, 10 deletions
diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx
index 134887664a4e..a60f9eda8b7e 100644
--- a/sc/source/core/opencl/formulagroupcl.cxx
+++ b/sc/source/core/opencl/formulagroupcl.cxx
@@ -1607,6 +1607,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
{
@@ -1668,18 +1673,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";
@@ -2149,9 +2161,35 @@ public:
virtual std::string GetBottom() SAL_OVERRIDE { return "1.0"; }
virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) const SAL_OVERRIDE
{
- return "(" + lhs + "/" + rhs + ")";
+ 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
diff --git a/sc/source/core/opencl/formulagroupcl_public.hxx b/sc/source/core/opencl/formulagroupcl_public.hxx
index 3b36770e6014..0ce60ce80e6b 100644
--- a/sc/source/core/opencl/formulagroupcl_public.hxx
+++ b/sc/source/core/opencl/formulagroupcl_public.hxx
@@ -11,6 +11,27 @@
#define INCLUDED_SC_SOURCE_CORE_OPENCL_FORMULAGROUPCL_PUBLIC_HXX
const char* publicFunc =
+ "\n"
+ "#define errIllegalFPOperation 503 // #NUM!\n"
+ "#define errNoValue 519 // #VALUE!\n"
+ "#define errDivisionByZero 532 // #DIV/0!\n"
+ "\n"
+ "double CreateDoubleError(ulong nErr)\n"
+ "{\n"
+ " return nan(nErr);\n"
+ "}\n"
+ "\n"
+ "uint GetDoubleErrorValue(double fVal)\n"
+ "{\n"
+ " if (isfinite(fVal))\n"
+ " return 0;\n"
+ " if (isinf(fVal))\n"
+ " return errIllegalFPOperation; // normal INF\n"
+ " if (as_ulong(fVal) & 0XFFFF0000u)\n"
+ " return errNoValue; // just a normal NAN\n"
+ " return (as_ulong(fVal) & 0XFFFF); // any other error\n"
+ "}\n"
+ "\n"
"int isNan(double a) { return isnan(a); }\n"
"double fsum_count(double a, double b, __private int *p) {\n"
" bool t = isNan(a);\n"