sc/source/core/data/formulacell.cxx | 8 + sc/source/core/opencl/formulagroupcl.cxx | 145 ++++++++++++++++++++++++++++++- sc/source/core/tool/formulagroup.cxx | 1 3 files changed, 153 insertions(+), 1 deletion(-)
New commits: commit 523860161f727076b30b884188b60ae97d816395 Author: Michael Meeks <michael.me...@suse.com> Date: Mon Jul 8 14:17:35 2013 +0100 Add new opencl placeholder backend for specific scenarios. diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index c3e8a951..6da2a5c 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2988,6 +2988,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 857f045..d92a471 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 commit 62b38b63d41261b3394d3dd042fcb7bccea84e34 Author: Michael Meeks <michael.me...@suse.com> Date: Mon Jul 8 11:57:39 2013 +0100 avoid regular re-creation of the formulagroup interpreter. diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx index 221a768..627c5f5 100644 --- a/sc/source/core/tool/formulagroup.cxx +++ b/sc/source/core/tool/formulagroup.cxx @@ -172,6 +172,7 @@ FormulaGroupInterpreter *FormulaGroupInterpreter::getStatic() if ( msInstance && bOpenCLEnabled != ScInterpreter::GetGlobalConfig().mbOpenCLEnabled ) { + bOpenCLEnabled = ScInterpreter::GetGlobalConfig().mbOpenCLEnabled; delete msInstance; msInstance = NULL; } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits