diff options
author | Michael Meeks <michael.meeks@suse.com> | 2013-07-08 14:17:35 +0100 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-07-11 00:25:36 -0400 |
commit | d5ae61ed2394b6945b969c61aea0adac2234f702 (patch) | |
tree | 24837674734d530dd3ba28296aee7912b7b31f0b /sc | |
parent | e67ae6c1ca5d0df2fb3b94dda32519288225fb30 (diff) |
Add new opencl placeholder backend for specific scenarios.
Diffstat (limited to 'sc')
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 8 | ||||
-rwxr-xr-x | sc/source/core/opencl/formulagroupcl.cxx | 145 |
2 files changed, 152 insertions, 1 deletions
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 17653c9a10c1..55f501030222 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -3064,6 +3064,14 @@ public: bool convert(ScTokenArray& rCode) { + { // debug to start with: + ScCompiler aComp( &mrDoc, mrPos, rCode); + aComp.SetGrammar(formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1); + OUStringBuffer aAsString; + aComp.CreateStringFromTokenArray(aAsString); + SAL_DEBUG("interpret formula: " << aAsString.makeStringAndClear()); + } + rCode.Reset(); for (const formula::FormulaToken* p = rCode.First(); p; p = rCode.Next()) { diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx index 857f045cd6c5..d92a4719f5d9 100755 --- a/sc/source/core/opencl/formulagroupcl.cxx +++ b/sc/source/core/opencl/formulagroupcl.cxx @@ -275,10 +275,153 @@ bool FormulaGroupInterpreterOpenCL::interpret(ScDocument& rDoc, const ScAddress& return true; } +/// Special case of formula compiler for groundwatering +class FormulaGroupInterpreterGroundwater : public FormulaGroupInterpreterSoftware +{ +public: + FormulaGroupInterpreterGroundwater() : + FormulaGroupInterpreterSoftware() + { + fprintf(stderr,"\n\n ***** Groundwater Backend *****\n\n\n"); + OclCalc::InitEnv(); + } + virtual ~FormulaGroupInterpreterGroundwater() + { + OclCalc::ReleaseOpenclRunEnv(); + } + + virtual ScMatrixRef inverseMatrix(const ScMatrix& /* rMat */) { return ScMatrixRef(); } + virtual bool interpret(ScDocument& rDoc, const ScAddress& rTopPos, + const ScFormulaCellGroupRef& xGroup, ScTokenArray& rCode); +}; + +#define RETURN_IF_FAIL(a,b) do { if (!(a)) { fprintf (stderr,b); return false; } } while (0) + +#include "compiler.hxx" + +// FIXME: really we should compile the formula and operate on the +// RPN representation which -should- be more compact and have no Open / Close +// or precedence issues; cf. rCode.FirstRPN() etc. +bool FormulaGroupInterpreterGroundwater::interpret(ScDocument& rDoc, const ScAddress& rTopPos, + const ScFormulaCellGroupRef& xGroup, + ScTokenArray& rCode) +{ + // Inputs: both of length xGroup->mnLength + OpCode eOp; // type of operation: ocAverage, ocMax, ocMin + const double *pArrayToSubtractOneElementFrom; + const double *pGroundWaterDataArray; + size_t nGroundWaterDataArrayLen; + + // Output: + double *pResult = new double[xGroup->mnLength]; + RETURN_IF_FAIL(pResult != NULL, "buffer alloc failed"); + std::vector<double> aMatrixContent; + + const formula::FormulaToken *p; + + // special cased formula parser: + + p = rCode.FirstNoSpaces(); + RETURN_IF_FAIL(p != NULL && p->GetOpCode() == ocOpen, "no opening ("); + + { + p = rCode.NextNoSpaces(); + RETURN_IF_FAIL(p != NULL, "no operator"); + + // Function: + eOp = p->GetOpCode(); + RETURN_IF_FAIL(eOp == ocAverage || eOp == ocMax || eOp == ocMin, "unexpected opcode"); + + { // function arguments + p = rCode.NextNoSpaces(); + RETURN_IF_FAIL(p != NULL && p->GetOpCode() == ocOpen, "missing opening ("); + + p = rCode.NextNoSpaces(); + RETURN_IF_FAIL(p != NULL, "no function argument"); + if (p->GetType() == formula::svDoubleVectorRef) + { + // FIXME: this is what I would expect; but table1.cxx's + // ScColumn::ResolveStaticReference as called from + // GroupTokenConverter::convert returns an ScMatrixToken un-conditionally + const formula::DoubleVectorRefToken* pDvr = static_cast<const formula::DoubleVectorRefToken*>(p); + const std::vector<const double*>& rArrays = pDvr->GetArrays(); + RETURN_IF_FAIL(rArrays.size() == 1, "unexpectedly large double ref array"); + RETURN_IF_FAIL(pDvr->GetArrayLength() == (size_t)xGroup->mnLength, "wrong double ref length"); + RETURN_IF_FAIL(pDvr->IsStartFixed() && pDvr->IsEndFixed(), "non-fixed ranges )"); + pGroundWaterDataArray = rArrays[0]; + nGroundWaterDataArrayLen = xGroup->mnLength; + } + else + { + RETURN_IF_FAIL(p->GetType() == formula::svMatrix, "unexpected fn. param type"); + const ScMatrixToken *pMatTok = static_cast<const ScMatrixToken *>(p); + pMatTok->GetMatrix()->GetDoubleArray( aMatrixContent ); + // FIXME: horrible hackery: the legacy / excel shared formula oddness, + // such that the 1st entry is not truly shared, making these a different + // shape. + if (aMatrixContent.size() > (size_t)xGroup->mnLength + 1) + { + fprintf(stderr, "Error size range mismatch: %ld vs %ld\n", + (long)aMatrixContent.size(), (long)xGroup->mnLength); + return false; + } + pGroundWaterDataArray = &aMatrixContent[0]; + nGroundWaterDataArrayLen = aMatrixContent.size(); + } + + p = rCode.NextNoSpaces(); + RETURN_IF_FAIL(p != NULL && p->GetOpCode() == ocClose, "missing closing )"); + } + + // Subtract operator + p = rCode.NextNoSpaces(); + RETURN_IF_FAIL(p != NULL && p->GetOpCode() == ocSub, "missing subtract opcode"); + + { // subtract parameter + p = rCode.NextNoSpaces(); + RETURN_IF_FAIL(p != NULL, "no tokens"); + RETURN_IF_FAIL(p->GetType() == formula::svSingleVectorRef, "not a single ref"); + const formula::SingleVectorRefToken* pSvr = static_cast<const formula::SingleVectorRefToken*>(p); + pArrayToSubtractOneElementFrom = pSvr->GetArray(); + RETURN_IF_FAIL(pSvr->GetArrayLength() == (size_t)xGroup->mnLength, "wrong single ref length"); + } + + p = rCode.NextNoSpaces(); + RETURN_IF_FAIL(p != NULL && p->GetOpCode() == ocClose, "missing closing )"); + } + + p = rCode.NextNoSpaces(); + RETURN_IF_FAIL(p == NULL, "has 5th"); + + static OclCalc ocl_calc; + + // Here we have all the data we need to dispatch our openCL kernel [ I hope ] + // so for: + // =AVERAGE(L$6:L$7701) - L6 + // we would get: + // eOp => ocAverage + // pGroundWaterDataArray => contains L$6:L$7701 + // pGroundWaterDataArrayLen => 7701 - 6 + 1 + // pArrayToSubtractOneElementFrom => contains L$5:L$7701 (overlapping) + // length of this array -> xGroup->mnLength + + fprintf (stderr, "Calculate !\n"); + + // Insert the double data, in rResult[i] back into the document + rDoc.SetFormulaResults(rTopPos, pResult, xGroup->mnLength); + + delete [] pResult; + SAL_DEBUG ("exit cleanly !"); + return true; +} + namespace opencl { sc::FormulaGroupInterpreter *createFormulaGroupInterpreter() { - return new sc::FormulaGroupInterpreterOpenCL(); + if (getenv("SC_GROUNDWATER")) + return new sc::FormulaGroupInterpreterGroundwater(); + else + return new sc::FormulaGroupInterpreterOpenCL(); } } // namespace opencl |