[Libreoffice-commits] core.git: Branch 'feature/calc-group-interpreter' - 2 commits - sc/source

Michael Meeks michael.meeks at suse.com
Mon Jul 8 06:15:44 PDT 2013


 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.meeks at 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.meeks at 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;
     }


More information about the Libreoffice-commits mailing list