summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@suse.com>2013-07-08 14:17:35 +0100
committerKohei Yoshida <kohei.yoshida@gmail.com>2013-07-11 00:25:36 -0400
commitd5ae61ed2394b6945b969c61aea0adac2234f702 (patch)
tree24837674734d530dd3ba28296aee7912b7b31f0b /sc
parente67ae6c1ca5d0df2fb3b94dda32519288225fb30 (diff)
Add new opencl placeholder backend for specific scenarios.
Diffstat (limited to 'sc')
-rw-r--r--sc/source/core/data/formulacell.cxx8
-rwxr-xr-xsc/source/core/opencl/formulagroupcl.cxx145
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