[Libreoffice-commits] core.git: 22 commits - sc/inc sc/Library_sc.mk sc/qa sc/source
Kohei Yoshida
kohei.yoshida at gmail.com
Wed Jul 10 21:25:06 PDT 2013
sc/Library_sc.mk | 1
sc/inc/column.hxx | 31
sc/inc/formulagroup.hxx | 3
sc/inc/sharedformula.hxx | 92 +
sc/qa/unit/ucalc.cxx | 77 -
sc/qa/unit/ucalc.hxx | 18
sc/qa/unit/ucalc_sharedformula.cxx | 80 +
sc/source/core/data/column.cxx | 114 +
sc/source/core/data/column2.cxx | 8
sc/source/core/data/column3.cxx | 323 +---
sc/source/core/data/formulacell.cxx | 8
sc/source/core/opencl/formulagroupcl.cxx | 247 ++-
sc/source/core/opencl/oclkernels.hxx | 207 +-
sc/source/core/opencl/openclwrapper.cxx | 2159 +++++++++++++++++++++----------
sc/source/core/opencl/openclwrapper.hxx | 145 +-
sc/source/core/tool/formulagroup.cxx | 14
sc/source/core/tool/sharedformula.cxx | 144 ++
17 files changed, 2456 insertions(+), 1215 deletions(-)
New commits:
commit 76c6a4e328546d96f97daadbaf846be0a72c112a
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Wed Jul 10 22:09:29 2013 -0400
Parse the token array in the RPN order.
Change-Id: I3770269e23980597c16dd613704bd7a9feb0aec9
diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx
index 04a67d2..dee465e 100755
--- a/sc/source/core/opencl/formulagroupcl.cxx
+++ b/sc/source/core/opencl/formulagroupcl.cxx
@@ -295,7 +295,7 @@ public:
const ScFormulaCellGroupRef& xGroup, ScTokenArray& rCode);
};
-#define RETURN_IF_FAIL(a,b) do { if (!(a)) { fprintf (stderr,b); return false; } } while (0)
+#define RETURN_IF_FAIL(a,b) do { if (!(a)) { fprintf (stderr,b"\n"); return false; } } while (0)
#include "compiler.hxx"
@@ -313,61 +313,36 @@ bool FormulaGroupInterpreterGroundwater::interpret(ScDocument& rDoc, const ScAdd
const double *pArrayToSubtractOneElementFrom;
const double *pGroundWaterDataArray;
- // Output:
- std::vector<double> aMatrixContent;
+ const formula::FormulaToken* p = rCode.FirstRPN();
+ RETURN_IF_FAIL(p != NULL && p->GetOpCode() == ocPush && p->GetType() == formula::svDoubleVectorRef, "double vector ref expected");
- const formula::FormulaToken *p;
+ // Get the range reference vector.
+ 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];
- // special cased formula parser:
+ // Function:
+ p = rCode.NextRPN();
+ RETURN_IF_FAIL(p != NULL, "no operator");
+ eOp = p->GetOpCode();
+ RETURN_IF_FAIL(eOp == ocAverage || eOp == ocMax || eOp == ocMin, "unexpected opcode - expected either average, max, or min");
- p = rCode.FirstNoSpaces();
- RETURN_IF_FAIL(p != NULL && p->GetOpCode() == ocOpen, "no opening (");
+ p = rCode.NextRPN();
+ RETURN_IF_FAIL(p != NULL && p->GetOpCode() == ocPush && p->GetType() == formula::svSingleVectorRef, "single vector ref expected");
- {
- 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");
- RETURN_IF_FAIL(p->GetType() == formula::svDoubleVectorRef, "wrong type of fn argument");
- 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];
-
- p = rCode.NextNoSpaces();
- RETURN_IF_FAIL(p != NULL && p->GetOpCode() == ocClose, "missing closing )");
- }
+ // Get the single reference vector.
+ 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");
- // 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.NextRPN();
+ RETURN_IF_FAIL(p != NULL && p->GetOpCode() == ocSub, "missing subtract opcode");
- p = rCode.NextNoSpaces();
- RETURN_IF_FAIL(p == NULL, "has 5th");
+ p = rCode.NextRPN();
+ RETURN_IF_FAIL(p == NULL, "there should be no more token");
static OclCalc ocl_calc;
@@ -380,7 +355,7 @@ bool FormulaGroupInterpreterGroundwater::interpret(ScDocument& rDoc, const ScAdd
// pArrayToSubtractOneElementFrom => contains L$5:L$7701 (ie. a copy)
// length of this array -> xGroup->mnLength
- fprintf (stderr, "Calculate !\n");
+ fprintf (stderr, "Calculate !");
double *pResult = ocl_calc.OclSimpleDeltaOperation( eOp, pGroundWaterDataArray,
pArrayToSubtractOneElementFrom,
commit de9dc7b88d7d7437ebc583b029fb46e2f1db8319
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Wed Jul 10 19:46:46 2013 -0400
Move more methods to SharedFormulaUtil.
Change-Id: Ibd58f5d15292805d50823223d1ebe94e7b51b808
diff --git a/sc/inc/sharedformula.hxx b/sc/inc/sharedformula.hxx
index 6767d4a..fa75e80 100644
--- a/sc/inc/sharedformula.hxx
+++ b/sc/inc/sharedformula.hxx
@@ -66,6 +66,16 @@ public:
static void splitFormulaCellGroup(const CellStoreType::position_type& aPos);
/**
+ * See if two specified adjacent formula cells can be merged, and if they
+ * can, merge them into the same group.
+ *
+ * @param rPos position object of the first cell
+ * @param rCell1 first cell
+ * @param rCell2 second cell located immediately below the first cell.
+ */
+ static void joinFormulaCells(
+ const CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2);
+ /**
* Merge with an existing formula group (if any) located immediately above
* if the cell at specified position is a formula cell, and its formula
* tokens are identical to that of the above formula group.
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index de8adde..2136e04 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -306,69 +306,6 @@ sc::CellStoreType::iterator ScColumn::GetPositionToInsert( SCROW nRow )
return GetPositionToInsert(maCells.begin(), nRow);
}
-namespace {
-
-void joinFormulaCells(const sc::CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
-{
- ScFormulaCell::CompareState eState = rCell1.CompareByTokenArray(rCell2);
- if (eState == ScFormulaCell::NotEqual)
- return;
-
- SCROW nRow = rPos.first->position + rPos.second;
-
- // Formula tokens equal those of the previous formula cell.
- ScFormulaCellGroupRef xGroup1 = rCell1.GetCellGroup();
- ScFormulaCellGroupRef xGroup2 = rCell2.GetCellGroup();
- if (xGroup1)
- {
- if (xGroup2)
- {
- // Both cell 1 and cell 2 are shared. Merge them together.
- if (xGroup1.get() == xGroup2.get())
- // They belong to the same group.
- return;
-
- // Set the group object from cell 1 to all cells in group 2.
- xGroup1->mnLength += xGroup2->mnLength;
- size_t nOffset = rPos.second + 1; // position of cell 2
- for (size_t i = 0, n = xGroup2->mnLength; i < n; ++i)
- {
- ScFormulaCell& rCell = *sc::formula_block::at(*rPos.first->data, nOffset+i);
- rCell.SetCellGroup(xGroup1);
- }
- }
- else
- {
- // cell 1 is shared but cell 2 is not.
- rCell2.SetCellGroup(xGroup1);
- ++xGroup1->mnLength;
- }
- }
- else
- {
- if (xGroup2)
- {
- // cell 1 is not shared, but cell 2 is already shared.
- rCell1.SetCellGroup(xGroup2);
- xGroup2->mnStart = nRow;
- ++xGroup2->mnLength;
- }
- else
- {
- // neither cells are shared.
- xGroup1.reset(new ScFormulaCellGroup);
- xGroup1->mnStart = nRow;
- xGroup1->mbInvariant = (eState == ScFormulaCell::EqualInvariant);
- xGroup1->mnLength = 2;
-
- rCell1.SetCellGroup(xGroup1);
- rCell2.SetCellGroup(xGroup1);
- }
- }
-}
-
-}
-
void ScColumn::JoinNewFormulaCell(
const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell ) const
{
@@ -378,14 +315,14 @@ void ScColumn::JoinNewFormulaCell(
ScFormulaCell& rPrev = *sc::formula_block::at(*aPos.first->data, aPos.second-1);
sc::CellStoreType::position_type aPosPrev = aPos;
--aPosPrev.second;
- joinFormulaCells(aPosPrev, rPrev, rCell);
+ sc::SharedFormulaUtil::joinFormulaCells(aPosPrev, rPrev, rCell);
}
// Check the next row position for possible grouping.
if (aPos.first->type == sc::element_type_formula && aPos.second+1 < aPos.first->size)
{
ScFormulaCell& rNext = *sc::formula_block::at(*aPos.first->data, aPos.second+1);
- joinFormulaCells(aPos, rCell, rNext);
+ sc::SharedFormulaUtil::joinFormulaCells(aPos, rCell, rNext);
}
}
diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx
index c1bc564..5cdfc785 100644
--- a/sc/source/core/tool/sharedformula.cxx
+++ b/sc/source/core/tool/sharedformula.cxx
@@ -62,9 +62,7 @@ void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type
}
}
-namespace {
-
-void joinFormulaCells(const sc::CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
+void SharedFormulaUtil::joinFormulaCells(const CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
{
ScFormulaCell::CompareState eState = rCell1.CompareByTokenArray(rCell2);
if (eState == ScFormulaCell::NotEqual)
@@ -123,8 +121,6 @@ void joinFormulaCells(const sc::CellStoreType::position_type& rPos, ScFormulaCel
}
}
-}
-
void SharedFormulaUtil::joinFormulaCellAbove(const CellStoreType::position_type& aPos)
{
if (aPos.first->type != sc::element_type_formula)
commit 1fd0ab0c53e73b50857e5bfed4b307468202354f
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Wed Jul 10 19:34:34 2013 -0400
Move these methods out of ScColumn since they don't operate on column.
Change-Id: I1a03b9b18dd236138306fd545e961a5443e22bc8
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 01e9ef7..2c59b77 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -503,15 +503,6 @@ public:
void UnshareFormulaCell( const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell ) const;
/**
- * Split existing shared formula range at specified position. The cell at
- * specified position becomes the top cell of the lower shared formula
- * range after this call.
- */
- void SplitFormulaCellGroup( const sc::CellStoreType::position_type& aPos ) const;
-
- void JoinFormulaCellAbove( const sc::CellStoreType::position_type& aPos ) const;
-
- /**
* Regroup formula cells for the entire column.
*/
void RegroupFormulaCells();
diff --git a/sc/inc/sharedformula.hxx b/sc/inc/sharedformula.hxx
index fcab6d7..6767d4a 100644
--- a/sc/inc/sharedformula.hxx
+++ b/sc/inc/sharedformula.hxx
@@ -11,6 +11,7 @@
#define SC_SHAREDFORMULA_HXX
#include "formulacell.hxx"
+#include "mtvelements.hxx"
namespace sc {
@@ -18,6 +19,10 @@ class SharedFormulaUtil
{
public:
+ /**
+ * Group formula cells stored in the passed container. The formula cells
+ * in the container are assumed to be all <b>non-shared</b>.
+ */
template<typename _Iter>
static void groupFormulaCells(const _Iter& itBeg, const _Iter& itEnd)
{
@@ -49,6 +54,25 @@ public:
pCur->SetCellGroup(xGroup);
}
}
+
+ /**
+ * Split existing shared formula range at specified position. The cell at
+ * specified position becomes the top cell of the lower shared formula
+ * range after this call. This method does nothing if the cell at
+ * specified position is not a formula cell.
+ *
+ * @param aPos position of cell to examine.
+ */
+ static void splitFormulaCellGroup(const CellStoreType::position_type& aPos);
+
+ /**
+ * Merge with an existing formula group (if any) located immediately above
+ * if the cell at specified position is a formula cell, and its formula
+ * tokens are identical to that of the above formula group.
+ *
+ * @param aPos position of cell to examine.
+ */
+ static void joinFormulaCellAbove(const CellStoreType::position_type& aPos);
};
}
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index b777905..730fed4 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -1383,12 +1383,12 @@ public:
sc::CellStoreType::position_type aPos =
rDestCells.position(maDestPos.miCellPos, nTopRow);
maDestPos.miCellPos = aPos.first;
- mrDestCol.JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
size_t nLastRow = nTopRow + nDataSize;
if (nLastRow < static_cast<size_t>(MAXROW))
{
aPos = rDestCells.position(maDestPos.miCellPos, nLastRow+1);
- mrDestCol.JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
}
setDefaultAttrsToDest(nTopRow, nDataSize);
@@ -2170,15 +2170,15 @@ void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
// Split the formula grouping at the top and bottom boundaries.
sc::CellStoreType::position_type aPos = maCells.position(nStartRow);
- SplitFormulaCellGroup(aPos);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
aPos = maCells.position(aPos.first, nEndRow+1);
- SplitFormulaCellGroup(aPos);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
// Do the same with the destination column.
aPos = rCol.maCells.position(nStartRow);
- rCol.SplitFormulaCellGroup(aPos);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
aPos = rCol.maCells.position(aPos.first, nEndRow+1);
- rCol.SplitFormulaCellGroup(aPos);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
// Move the broadcasters to the destination column.
maBroadcasters.transfer(nStartRow, nEndRow, rCol.maBroadcasters, nStartRow);
@@ -2187,9 +2187,9 @@ void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
// Re-group transferred formula cells.
aPos = rCol.maCells.position(nStartRow);
- rCol.JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
aPos = rCol.maCells.position(aPos.first, nEndRow+1);
- rCol.JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
CellStorageModified();
rCol.CellStorageModified();
@@ -2315,11 +2315,11 @@ bool ScColumn::UpdateReferenceOnCopy(
// The formula groups at the top and bottom boundaries are expected to
// have been split prior to this call. Here, we only do the joining.
- JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
if (rRange.aEnd.Row() < MAXROW)
{
aPos = maCells.position(aPos.first, rRange.aEnd.Row()+1);
- JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
}
return aHandler.isUpdated();
@@ -2341,12 +2341,12 @@ bool ScColumn::UpdateReference(
if (ValidRow(nSplitPos))
{
sc::CellStoreType::position_type aPos = maCells.position(nSplitPos);
- SplitFormulaCellGroup(aPos);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
nSplitPos = rRange.aEnd.Row() + 1;
if (ValidRow(nSplitPos))
{
aPos = maCells.position(aPos.first, nSplitPos);
- SplitFormulaCellGroup(aPos);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
}
}
}
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 4fb06c3..de8adde 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -281,7 +281,7 @@ void ScColumn::DeleteRow( SCROW nStartRow, SCSIZE nSize )
ShiftFormulaPosHandler aShiftFormulaFunc;
sc::ProcessFormula(aPos.first, maCells, nStartRow, MAXROW, aShiftFormulaFunc);
- JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
// Single cell broadcasts on deleted cells.
BroadcastCells(aDeleteRowsFunc.getNonEmptyRows());
@@ -420,13 +420,13 @@ void ScColumn::DetachFormulaCells(
const sc::CellStoreType::position_type& aPos, size_t nLength )
{
// Split formula grouping at the top and bottom boundaries.
- SplitFormulaCellGroup(aPos);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
size_t nRow = aPos.first->position + aPos.second;
size_t nNextTopRow = nRow + nLength; // start row of next formula group.
if (ValidRow(nNextTopRow))
{
sc::CellStoreType::position_type aPos2 = maCells.position(aPos.first, nNextTopRow);
- SplitFormulaCellGroup(aPos2);
+ sc::SharedFormulaUtil::splitFormulaCellGroup(aPos2);
}
if (pDocument->IsClipOrUndo())
@@ -555,74 +555,6 @@ void ScColumn::UnshareFormulaCell(
rCell.SetCellGroup(xNone);
}
-void ScColumn::SplitFormulaCellGroup( const sc::CellStoreType::position_type& aPos ) const
-{
- SCROW nRow = aPos.first->position + aPos.second;
-
- if (aPos.first->type != sc::element_type_formula)
- // Not a formula cell block.
- return;
-
- if (aPos.second == 0)
- // Split position coincides with the block border. Nothing to do.
- return;
-
- sc::formula_block::iterator it = sc::formula_block::begin(*aPos.first->data);
- std::advance(it, aPos.second);
- ScFormulaCell& rTop = **it;
- if (!rTop.IsShared())
- // Not a shared formula.
- return;
-
- if (nRow == rTop.GetSharedTopRow())
- // Already the top cell of a shared group.
- return;
-
- ScFormulaCellGroupRef xGroup = rTop.GetCellGroup();
-
- ScFormulaCellGroupRef xGroup2(new ScFormulaCellGroup);
- xGroup2->mbInvariant = xGroup->mbInvariant;
- xGroup2->mnStart = nRow;
- xGroup2->mnLength = xGroup->mnStart + xGroup->mnLength - nRow;
-
- xGroup->mnLength = nRow - xGroup->mnStart;
-
- // Apply the lower group object to the lower cells.
-#if DEBUG_COLUMN_STORAGE
- if (xGroup2->mnStart + xGroup2->mnLength > aPos.first->position + aPos.first->size)
- {
- cerr << "ScColumn::SplitFormulaCellGroup: Shared formula region goes beyond the formula block. Not good." << endl;
- cerr.flush();
- abort();
- }
-#endif
- sc::formula_block::iterator itEnd = it;
- std::advance(itEnd, xGroup2->mnLength);
- for (; it != itEnd; ++it)
- {
- ScFormulaCell& rCell = **it;
- rCell.SetCellGroup(xGroup2);
- }
-}
-
-void ScColumn::JoinFormulaCellAbove( const sc::CellStoreType::position_type& aPos ) const
-{
- if (aPos.first->type != sc::element_type_formula)
- // This is not a formula cell.
- return;
-
- if (aPos.second == 0)
- // This cell is already the top cell in a formula block; the previous
- // cell is not a formula cell.
- return;
-
- ScFormulaCell& rPrev = *sc::formula_block::at(*aPos.first->data, aPos.second-1);
- ScFormulaCell& rCell = *sc::formula_block::at(*aPos.first->data, aPos.second);
- sc::CellStoreType::position_type aPosPrev = aPos;
- --aPosPrev.second;
- joinFormulaCells(aPosPrev, rPrev, rCell);
-}
-
sc::CellStoreType::iterator ScColumn::GetPositionToInsert( const sc::CellStoreType::iterator& it, SCROW nRow )
{
// See if we are overwriting an existing formula cell.
@@ -1545,14 +1477,14 @@ public:
// Merge with the previous formula group (if any).
aPos = rDestCells.position(itDestPos, nDestRow);
- mrDestColumn.JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
// Merge with the next formula group (if any).
size_t nNextRow = nDestRow + it->size;
if (ValidRow(nNextRow))
{
aPos = rDestCells.position(aPos.first, nNextRow);
- mrDestColumn.JoinFormulaCellAbove(aPos);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
}
}
break;
diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx
index 7b6ac84..c1bc564 100644
--- a/sc/source/core/tool/sharedformula.cxx
+++ b/sc/source/core/tool/sharedformula.cxx
@@ -8,10 +8,140 @@
*/
#include "sharedformula.hxx"
+#include "calcmacros.hxx"
namespace sc {
+void SharedFormulaUtil::splitFormulaCellGroup(const CellStoreType::position_type& aPos)
+{
+ SCROW nRow = aPos.first->position + aPos.second;
+ if (aPos.first->type != sc::element_type_formula)
+ // Not a formula cell block.
+ return;
+
+ if (aPos.second == 0)
+ // Split position coincides with the block border. Nothing to do.
+ return;
+
+ sc::formula_block::iterator it = sc::formula_block::begin(*aPos.first->data);
+ std::advance(it, aPos.second);
+ ScFormulaCell& rTop = **it;
+ if (!rTop.IsShared())
+ // Not a shared formula.
+ return;
+
+ if (nRow == rTop.GetSharedTopRow())
+ // Already the top cell of a shared group.
+ return;
+
+ ScFormulaCellGroupRef xGroup = rTop.GetCellGroup();
+
+ ScFormulaCellGroupRef xGroup2(new ScFormulaCellGroup);
+ xGroup2->mbInvariant = xGroup->mbInvariant;
+ xGroup2->mnStart = nRow;
+ xGroup2->mnLength = xGroup->mnStart + xGroup->mnLength - nRow;
+
+ xGroup->mnLength = nRow - xGroup->mnStart;
+
+ // Apply the lower group object to the lower cells.
+#if DEBUG_COLUMN_STORAGE
+ if (xGroup2->mnStart + xGroup2->mnLength > aPos.first->position + aPos.first->size)
+ {
+ cerr << "ScColumn::SplitFormulaCellGroup: Shared formula region goes beyond the formula block. Not good." << endl;
+ cerr.flush();
+ abort();
+ }
+#endif
+ sc::formula_block::iterator itEnd = it;
+ std::advance(itEnd, xGroup2->mnLength);
+ for (; it != itEnd; ++it)
+ {
+ ScFormulaCell& rCell = **it;
+ rCell.SetCellGroup(xGroup2);
+ }
+}
+
+namespace {
+
+void joinFormulaCells(const sc::CellStoreType::position_type& rPos, ScFormulaCell& rCell1, ScFormulaCell& rCell2)
+{
+ ScFormulaCell::CompareState eState = rCell1.CompareByTokenArray(rCell2);
+ if (eState == ScFormulaCell::NotEqual)
+ return;
+
+ SCROW nRow = rPos.first->position + rPos.second;
+
+ // Formula tokens equal those of the previous formula cell.
+ ScFormulaCellGroupRef xGroup1 = rCell1.GetCellGroup();
+ ScFormulaCellGroupRef xGroup2 = rCell2.GetCellGroup();
+ if (xGroup1)
+ {
+ if (xGroup2)
+ {
+ // Both cell 1 and cell 2 are shared. Merge them together.
+ if (xGroup1.get() == xGroup2.get())
+ // They belong to the same group.
+ return;
+
+ // Set the group object from cell 1 to all cells in group 2.
+ xGroup1->mnLength += xGroup2->mnLength;
+ size_t nOffset = rPos.second + 1; // position of cell 2
+ for (size_t i = 0, n = xGroup2->mnLength; i < n; ++i)
+ {
+ ScFormulaCell& rCell = *sc::formula_block::at(*rPos.first->data, nOffset+i);
+ rCell.SetCellGroup(xGroup1);
+ }
+ }
+ else
+ {
+ // cell 1 is shared but cell 2 is not.
+ rCell2.SetCellGroup(xGroup1);
+ ++xGroup1->mnLength;
+ }
+ }
+ else
+ {
+ if (xGroup2)
+ {
+ // cell 1 is not shared, but cell 2 is already shared.
+ rCell1.SetCellGroup(xGroup2);
+ xGroup2->mnStart = nRow;
+ ++xGroup2->mnLength;
+ }
+ else
+ {
+ // neither cells are shared.
+ xGroup1.reset(new ScFormulaCellGroup);
+ xGroup1->mnStart = nRow;
+ xGroup1->mbInvariant = (eState == ScFormulaCell::EqualInvariant);
+ xGroup1->mnLength = 2;
+
+ rCell1.SetCellGroup(xGroup1);
+ rCell2.SetCellGroup(xGroup1);
+ }
+ }
+}
+
+}
+
+void SharedFormulaUtil::joinFormulaCellAbove(const CellStoreType::position_type& aPos)
+{
+ if (aPos.first->type != sc::element_type_formula)
+ // This is not a formula cell.
+ return;
+
+ if (aPos.second == 0)
+ // This cell is already the top cell in a formula block; the previous
+ // cell is not a formula cell.
+ return;
+
+ ScFormulaCell& rPrev = *sc::formula_block::at(*aPos.first->data, aPos.second-1);
+ ScFormulaCell& rCell = *sc::formula_block::at(*aPos.first->data, aPos.second);
+ sc::CellStoreType::position_type aPosPrev = aPos;
+ --aPosPrev.second;
+ joinFormulaCells(aPosPrev, rPrev, rCell);
+}
}
commit 0797dd8714413f8319515df9831a86703b589558
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Wed Jul 10 16:32:39 2013 -0400
Group formula cells in ScColumn::MixData().
Change-Id: I38186e2bf82ed56fbe859b17dcc1d31f36471bd8
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 5815fd0..d431c3c 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -251,6 +251,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/tool/refupdat \
sc/source/core/tool/scmatrix \
sc/source/core/tool/scopetools \
+ sc/source/core/tool/sharedformula \
sc/source/core/tool/simplerangelist \
sc/source/core/tool/stringutil \
sc/source/core/tool/stylehelper \
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index d024007..01e9ef7 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -487,17 +487,18 @@ public:
bool HasBroadcaster() const;
void BroadcastCells( const std::vector<SCROW>& rRows );
- void EndFormulaListening( sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2 );
void InterpretDirtyCells( SCROW nRow1, SCROW nRow2 );
void JoinNewFormulaCell( const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell ) const;
/**
- * Detouch a formula cell that's about to be deleted, or removed from
+ * Detach a formula cell that's about to be deleted, or removed from
* document storage (if that ever happens).
*/
- void DetouchFormulaCell( const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell ) const;
+ void DetachFormulaCell( const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell );
+
+ void DetachFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength );
void UnshareFormulaCell( const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell ) const;
@@ -515,14 +516,6 @@ public:
*/
void RegroupFormulaCells();
- /**
- * Regroup existing formula cells when a range of new cells are inserted.
- *
- * @param nRow1 first row of inserted new cell span.
- * @param nRow2 last row of inserted new cell span.
- */
- void RegroupFormulaCells( SCROW nRow1, SCROW nRow2 );
-
#if DEBUG_COLUMN_STORAGE
void DumpFormulaGroups() const;
#endif
diff --git a/sc/inc/sharedformula.hxx b/sc/inc/sharedformula.hxx
new file mode 100644
index 0000000..fcab6d7
--- /dev/null
+++ b/sc/inc/sharedformula.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef SC_SHAREDFORMULA_HXX
+#define SC_SHAREDFORMULA_HXX
+
+#include "formulacell.hxx"
+
+namespace sc {
+
+class SharedFormulaUtil
+{
+public:
+
+ template<typename _Iter>
+ static void groupFormulaCells(const _Iter& itBeg, const _Iter& itEnd)
+ {
+ _Iter it = itBeg;
+ ScFormulaCell* pPrev = *it;
+ ScFormulaCell* pCur = NULL;
+ for (++it; it != itEnd; ++it, pPrev = pCur)
+ {
+ pCur = *it;
+ ScFormulaCell::CompareState eState = pPrev->CompareByTokenArray(*pPrev);
+ if (eState == ScFormulaCell::NotEqual)
+ continue;
+
+ ScFormulaCellGroupRef xGroup = pPrev->GetCellGroup();
+ if (xGroup)
+ {
+ // Extend the group.
+ ++xGroup->mnLength;
+ pCur->SetCellGroup(xGroup);
+ continue;
+ }
+
+ // Create a new group.
+ xGroup.reset(new ScFormulaCellGroup);
+ xGroup->mnStart = pPrev->aPos.Row();
+ xGroup->mnLength = 2;
+ xGroup->mbInvariant = (eState == ScFormulaCell::EqualInvariant);
+ pPrev->SetCellGroup(xGroup);
+ pCur->SetCellGroup(xGroup);
+ }
+ }
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index ad51473..b777905 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -39,6 +39,7 @@
#include "mtvcellfunc.hxx"
#include "columnspanset.hxx"
#include "scopetools.hxx"
+#include "sharedformula.hxx"
#include <svl/poolcach.hxx>
#include <svl/zforlist.hxx>
@@ -868,8 +869,8 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
// TODO: Find out a way to adjust references without cloning new instances.
boost::scoped_ptr<ScFormulaCell> pOld1(*itf1);
boost::scoped_ptr<ScFormulaCell> pOld2(*itf2);
- DetouchFormulaCell(aPos1, **itf1);
- DetouchFormulaCell(aPos2, **itf2);
+ DetachFormulaCell(aPos1, **itf1);
+ DetachFormulaCell(aPos2, **itf2);
ScFormulaCell* pNew1 = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *pOld2);
ScFormulaCell* pNew2 = cloneFormulaCell(pDocument, ScAddress(nCol, nRow2, nTab), *pOld1);
*itf1 = pNew1;
@@ -920,7 +921,7 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
{
// cell 1 is empty and cell 2 is a formula cell.
ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
- DetouchFormulaCell(aPos2, *aCell2.mpFormula);
+ DetachFormulaCell(aPos2, *aCell2.mpFormula);
it1 = maCells.set(it1, nRow1, pNew);
maCells.set_empty(it1, nRow2, nRow2); // original formula cell gets deleted.
ActivateNewFormulaCell(it1, nRow1, *pNew);
@@ -964,7 +965,7 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
{
// cell 1 is a formula cell and cell 2 is empty.
ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow2, nTab), *aCell1.mpFormula);
- DetouchFormulaCell(aPos1, *aCell1.mpFormula);
+ DetachFormulaCell(aPos1, *aCell1.mpFormula);
it1 = maCells.set_empty(it1, nRow1, nRow1); // original formula cell is gone.
it1 = maCells.set(it1, nRow2, pNew);
ActivateNewFormulaCell(it1, nRow2, *pNew);
@@ -999,7 +1000,7 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
break;
case CELLTYPE_FORMULA:
{
- DetouchFormulaCell(aPos2, *aCell2.mpFormula);
+ DetachFormulaCell(aPos2, *aCell2.mpFormula);
ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
it1 = maCells.set(it1, nRow1, pNew);
ActivateNewFormulaCell(it1, nRow1, *pNew);
@@ -1032,7 +1033,7 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
case CELLTYPE_FORMULA:
{
// cell 1 - string, cell 2 - formula
- DetouchFormulaCell(aPos2, *aCell2.mpFormula);
+ DetachFormulaCell(aPos2, *aCell2.mpFormula);
ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
it1 = maCells.set(it1, nRow1, pNew);
ActivateNewFormulaCell(it1, nRow1, *pNew);
@@ -1061,7 +1062,7 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
break;
case CELLTYPE_FORMULA:
{
- DetouchFormulaCell(aPos2, *aCell2.mpFormula);
+ DetachFormulaCell(aPos2, *aCell2.mpFormula);
ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
it1 = maCells.set(it1, nRow1, pNew);
ActivateNewFormulaCell(it1, nRow1, *pNew);
@@ -1078,7 +1079,7 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
case CELLTYPE_FORMULA:
{
// cell 1 is a formula cell and cell 2 is not.
- DetouchFormulaCell(aPos1, *aCell1.mpFormula);
+ DetachFormulaCell(aPos1, *aCell1.mpFormula);
ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow2, nTab), *aCell1.mpFormula);
switch (aCell2.meType)
{
@@ -1371,7 +1372,8 @@ public:
}
// Group the cloned formula cells.
- groupFormulaCells(aCloned);
+ if (!aCloned.empty())
+ sc::SharedFormulaUtil::groupFormulaCells(aCloned.begin(), aCloned.end());
sc::CellStoreType& rDestCells = mrDestCol.GetCellStore();
maDestPos.miCellPos = rDestCells.set(
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index aa4dd0e..7b38918 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1530,10 +1530,6 @@ void ScColumn::CellStorageModified()
#endif
}
-void ScColumn::RegroupFormulaCells( SCROW /*nRow1*/, SCROW /*nRow2*/ )
-{
-}
-
#if DEBUG_COLUMN_STORAGE
namespace {
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 8352d46..4fb06c3 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -45,6 +45,7 @@
#include "mtvcellfunc.hxx"
#include "scopetools.hxx"
#include "editutil.hxx"
+#include "sharedformula.hxx"
#include <com/sun/star/i18n/LocaleDataItem.hpp>
@@ -91,29 +92,6 @@ void ScColumn::BroadcastCells( const std::vector<SCROW>& rRows )
broadcastCells(*pDocument, nCol, nTab, rRows);
}
-namespace {
-
-class EndListeningHandler
-{
- ScDocument* mpDoc;
-public:
- EndListeningHandler(ScDocument* pDoc) : mpDoc(pDoc) {}
-
- void operator() (size_t, ScFormulaCell* p)
- {
- p->EndListeningTo(mpDoc);
- }
-};
-
-}
-
-void ScColumn::EndFormulaListening( sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2 )
-{
- EndListeningHandler aFunc(pDocument);
- rBlockPos.miCellPos =
- sc::ProcessFormula(rBlockPos.miCellPos, maCells, nRow1, nRow2, aFunc);
-}
-
struct DirtyCellInterpreter
{
void operator() (size_t, ScFormulaCell* p)
@@ -411,8 +389,8 @@ void ScColumn::JoinNewFormulaCell(
}
}
-void ScColumn::DetouchFormulaCell(
- const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell ) const
+void ScColumn::DetachFormulaCell(
+ const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell )
{
if (!pDocument->IsClipOrUndo())
// Have the dying formula cell stop listening.
@@ -422,6 +400,42 @@ void ScColumn::DetouchFormulaCell(
UnshareFormulaCell(aPos, rCell);
}
+namespace {
+
+class DetachFormulaCellsHandler
+{
+ ScDocument* mpDoc;
+public:
+ DetachFormulaCellsHandler(ScDocument* pDoc) : mpDoc(pDoc) {}
+
+ void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
+ {
+ pCell->EndListeningTo(mpDoc);
+ }
+};
+
+}
+
+void ScColumn::DetachFormulaCells(
+ const sc::CellStoreType::position_type& aPos, size_t nLength )
+{
+ // Split formula grouping at the top and bottom boundaries.
+ SplitFormulaCellGroup(aPos);
+ size_t nRow = aPos.first->position + aPos.second;
+ size_t nNextTopRow = nRow + nLength; // start row of next formula group.
+ if (ValidRow(nNextTopRow))
+ {
+ sc::CellStoreType::position_type aPos2 = maCells.position(aPos.first, nNextTopRow);
+ SplitFormulaCellGroup(aPos2);
+ }
+
+ if (pDocument->IsClipOrUndo())
+ return;
+
+ DetachFormulaCellsHandler aFunc(pDocument);
+ sc::ProcessFormula(aPos.first, maCells, nRow, nNextTopRow-1, aFunc);
+}
+
void ScColumn::UnshareFormulaCell(
const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell ) const
{
@@ -617,7 +631,7 @@ sc::CellStoreType::iterator ScColumn::GetPositionToInsert( const sc::CellStoreTy
if (itRet->type == sc::element_type_formula)
{
ScFormulaCell& rCell = *sc::formula_block::at(*itRet->data, aPos.second);
- DetouchFormulaCell(aPos, rCell);
+ DetachFormulaCell(aPos, rCell);
}
return itRet;
@@ -1240,11 +1254,7 @@ void lcl_AddCode( ScTokenArray& rArr, const ScFormulaCell* pCell )
class MixDataHandler
{
ScColumn& mrDestColumn;
-
- sc::CellStoreType& mrDestCells;
- sc::CellStoreType::iterator miDestPos;
-
- sc::CellTextAttrStoreType& mrDestAttrs;
+ sc::ColumnBlockPosition& mrBlockPos;
sc::CellStoreType maNewCells;
sc::CellStoreType::iterator miNewCellsPos;
@@ -1256,37 +1266,30 @@ class MixDataHandler
public:
MixDataHandler(
- sc::ColumnBlockPosition* pBlockPos,
+ sc::ColumnBlockPosition& rBlockPos,
ScColumn& rDestColumn,
- sc::CellStoreType& rDestCells,
- sc::CellTextAttrStoreType& rDestAttrs,
SCROW nRow1, SCROW nRow2,
sal_uInt16 nFunction, bool bSkipEmpty) :
mrDestColumn(rDestColumn),
- mrDestCells(rDestCells),
- mrDestAttrs(rDestAttrs),
+ mrBlockPos(rBlockPos),
maNewCells(nRow2 - nRow1 + 1),
miNewCellsPos(maNewCells.begin()),
mnRowOffset(nRow1),
mnFunction(nFunction),
mbSkipEmpty(bSkipEmpty)
{
- if (pBlockPos)
- miDestPos = pBlockPos->miCellPos;
- else
- miDestPos = mrDestCells.begin();
}
void operator() (size_t nRow, double f)
{
- std::pair<sc::CellStoreType::iterator, size_t> aPos = mrDestCells.position(miDestPos, nRow);
- miDestPos = aPos.first;
- switch (miDestPos->type)
+ sc::CellStoreType::position_type aPos = mrDestColumn.GetCellStore().position(mrBlockPos.miCellPos, nRow);
+ mrBlockPos.miCellPos = aPos.first;
+ switch (aPos.first->type)
{
case sc::element_type_numeric:
{
// Both src and dest are of numeric type.
- bool bOk = lcl_DoFunction(f, sc::numeric_block::at(*miDestPos->data, aPos.second), mnFunction);
+ bool bOk = lcl_DoFunction(f, sc::numeric_block::at(*aPos.first->data, aPos.second), mnFunction);
if (bOk)
miNewCellsPos = maNewCells.set(miNewCellsPos, nRow-mnRowOffset, f);
@@ -1321,7 +1324,7 @@ public:
aArr.AddOpCode(eOp); // Function
// Second row
- ScFormulaCell* pDest = sc::formula_block::at(*miDestPos->data, aPos.second);
+ ScFormulaCell* pDest = sc::formula_block::at(*aPos.first->data, aPos.second);
lcl_AddCode(aArr, pDest);
miNewCellsPos = maNewCells.set(
@@ -1355,9 +1358,9 @@ public:
void operator() (size_t nRow, const ScFormulaCell* p)
{
- std::pair<sc::CellStoreType::iterator, size_t> aPos = mrDestCells.position(miDestPos, nRow);
- miDestPos = aPos.first;
- switch (miDestPos->type)
+ sc::CellStoreType::position_type aPos = mrDestColumn.GetCellStore().position(mrBlockPos.miCellPos, nRow);
+ mrBlockPos.miCellPos = aPos.first;
+ switch (aPos.first->type)
{
case sc::element_type_numeric:
{
@@ -1379,7 +1382,7 @@ public:
aArr.AddOpCode(eOp); // Function
// Second row
- aArr.AddDouble(sc::numeric_block::at(*miDestPos->data, aPos.second));
+ aArr.AddDouble(sc::numeric_block::at(*aPos.first->data, aPos.second));
miNewCellsPos = maNewCells.set(
miNewCellsPos, nRow-mnRowOffset,
@@ -1407,7 +1410,7 @@ public:
aArr.AddOpCode(eOp); // Function
// Second row
- ScFormulaCell* pDest = sc::formula_block::at(*miDestPos->data, aPos.second);
+ ScFormulaCell* pDest = sc::formula_block::at(*aPos.first->data, aPos.second);
lcl_AddCode(aArr, pDest);
miNewCellsPos = maNewCells.set(
@@ -1443,9 +1446,9 @@ public:
for (size_t i = 0; i < nDataSize; ++i)
{
size_t nDestRow = nTopRow + i;
- std::pair<sc::CellStoreType::iterator, size_t> aPos = mrDestCells.position(miDestPos, nDestRow);
- miDestPos = aPos.first;
- switch (miDestPos->type)
+ sc::CellStoreType::position_type aPos = mrDestColumn.GetCellStore().position(mrBlockPos.miCellPos, nDestRow);
+ mrBlockPos.miCellPos = aPos.first;
+ switch (aPos.first->type)
{
case sc::element_type_numeric:
case sc::element_type_string:
@@ -1457,7 +1460,7 @@ public:
ScTokenArray aArr;
// First row
- ScFormulaCell* pSrc = sc::formula_block::at(*miDestPos->data, aPos.second);
+ ScFormulaCell* pSrc = sc::formula_block::at(*aPos.first->data, aPos.second);
lcl_AddCode( aArr, pSrc);
// Operator
@@ -1488,21 +1491,17 @@ public:
/**
* Set the new cells to the destination (this) column.
*/
- void commit(sc::ColumnBlockPosition* pDestBlockPos)
+ void commit()
{
- sc::ColumnBlockPosition aDestBlockPos;
- if (pDestBlockPos)
- aDestBlockPos = *pDestBlockPos;
- else
- mrDestColumn.InitBlockPosition(aDestBlockPos);
+ sc::CellStoreType& rDestCells = mrDestColumn.GetCellStore();
// Stop all formula cells in the destination range first.
- sc::ColumnBlockPosition aCopy = aDestBlockPos;
- mrDestColumn.EndFormulaListening(aCopy, mnRowOffset, mnRowOffset + maNewCells.size() - 1);
+ sc::CellStoreType::position_type aPos = rDestCells.position(mrBlockPos.miCellPos, mnRowOffset);
+ mrDestColumn.DetachFormulaCells(aPos, maNewCells.size());
// Move the new cells to the destination range.
- sc::CellStoreType::iterator& itDestPos = aDestBlockPos.miCellPos;
- sc::CellTextAttrStoreType::iterator& itDestAttrPos = aDestBlockPos.miCellTextAttrPos;
+ sc::CellStoreType::iterator& itDestPos = mrBlockPos.miCellPos;
+ sc::CellTextAttrStoreType::iterator& itDestAttrPos = mrBlockPos.miCellTextAttrPos;
sc::CellStoreType::iterator it = maNewCells.begin(), itEnd = maNewCells.end();
for (; it != itEnd; ++it)
@@ -1516,33 +1515,50 @@ public:
{
sc::numeric_block::iterator itData = sc::numeric_block::begin(*it->data);
sc::numeric_block::iterator itDataEnd = sc::numeric_block::end(*it->data);
- itDestPos = mrDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
+ itDestPos = mrDestColumn.GetCellStore().set(itDestPos, nDestRow, itData, itDataEnd);
}
break;
case sc::element_type_string:
{
sc::string_block::iterator itData = sc::string_block::begin(*it->data);
sc::string_block::iterator itDataEnd = sc::string_block::end(*it->data);
- itDestPos = mrDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
+ itDestPos = rDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
}
break;
case sc::element_type_edittext:
{
sc::edittext_block::iterator itData = sc::edittext_block::begin(*it->data);
sc::edittext_block::iterator itDataEnd = sc::edittext_block::end(*it->data);
- itDestPos = mrDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
+ itDestPos = rDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
}
break;
case sc::element_type_formula:
{
sc::formula_block::iterator itData = sc::formula_block::begin(*it->data);
sc::formula_block::iterator itDataEnd = sc::formula_block::end(*it->data);
- itDestPos = mrDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
+
+ // Group new formula cells before inserting them.
+ sc::SharedFormulaUtil::groupFormulaCells(itData, itDataEnd);
+
+ // Insert the formula cells to the column.
+ itDestPos = rDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
+
+ // Merge with the previous formula group (if any).
+ aPos = rDestCells.position(itDestPos, nDestRow);
+ mrDestColumn.JoinFormulaCellAbove(aPos);
+
+ // Merge with the next formula group (if any).
+ size_t nNextRow = nDestRow + it->size;
+ if (ValidRow(nNextRow))
+ {
+ aPos = rDestCells.position(aPos.first, nNextRow);
+ mrDestColumn.JoinFormulaCellAbove(aPos);
+ }
}
break;
case sc::element_type_empty:
{
- itDestPos = mrDestCells.set_empty(itDestPos, nDestRow, nDestRow+it->size-1);
+ itDestPos = rDestCells.set_empty(itDestPos, nDestRow, nDestRow+it->size-1);
bHasContent = false;
}
break;
@@ -1550,19 +1566,17 @@ public:
;
}
+ sc::CellTextAttrStoreType& rDestAttrs = mrDestColumn.GetCellAttrStore();
if (bHasContent)
{
std::vector<sc::CellTextAttr> aAttrs(it->size, sc::CellTextAttr());
- itDestAttrPos = mrDestAttrs.set(itDestAttrPos, nDestRow, aAttrs.begin(), aAttrs.end());
+ itDestAttrPos = rDestAttrs.set(itDestAttrPos, nDestRow, aAttrs.begin(), aAttrs.end());
}
else
- itDestAttrPos = mrDestAttrs.set_empty(itDestAttrPos, nDestRow, nDestRow+it->size-1);
+ itDestAttrPos = rDestAttrs.set_empty(itDestAttrPos, nDestRow, nDestRow+it->size-1);
}
maNewCells.release();
-
- if (pDestBlockPos)
- *pDestBlockPos = aDestBlockPos;
}
};
@@ -1575,11 +1589,13 @@ void ScColumn::MixData(
// destination (this column) block position.
sc::ColumnBlockPosition* p = rCxt.getBlockPosition(nTab, nCol);
- MixDataHandler aFunc(p, *this, maCells, maCellTextAttrs, nRow1, nRow2, nFunction, bSkipEmpty);
+ if (!p)
+ return;
+
+ MixDataHandler aFunc(*p, *this, nRow1, nRow2, nFunction, bSkipEmpty);
sc::ParseAll(rSrcCol.maCells.begin(), rSrcCol.maCells, nRow1, nRow2, aFunc, aFunc);
- aFunc.commit(p);
- RegroupFormulaCells(nRow1, nRow2);
+ aFunc.commit();
CellStorageModified();
}
diff --git a/sc/source/core/tool/sharedformula.cxx b/sc/source/core/tool/sharedformula.cxx
new file mode 100644
index 0000000..7b6ac84
--- /dev/null
+++ b/sc/source/core/tool/sharedformula.cxx
@@ -0,0 +1,18 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "sharedformula.hxx"
+
+namespace sc {
+
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 217896aa33e40b113fafdaa109d02992f7d9506a
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Wed Jul 10 11:58:49 2013 -0400
Generate Reverse Polish token array (RPN) at the start.
Change-Id: Idcac01820fab536cebebcc437e206b6900511600
diff --git a/sc/inc/formulagroup.hxx b/sc/inc/formulagroup.hxx
index e645968..9963fc9 100644
--- a/sc/inc/formulagroup.hxx
+++ b/sc/inc/formulagroup.hxx
@@ -39,6 +39,9 @@ class SC_DLLPUBLIC FormulaGroupInterpreter
protected:
FormulaGroupInterpreter() {}
virtual ~FormulaGroupInterpreter() {}
+
+ static void generateRPNCode(ScDocument& rDoc, const ScAddress& rPos, ScTokenArray& rCode);
+
public:
static FormulaGroupInterpreter *getStatic();
diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx
index 8bc0224..04a67d2 100755
--- a/sc/source/core/opencl/formulagroupcl.cxx
+++ b/sc/source/core/opencl/formulagroupcl.cxx
@@ -65,6 +65,8 @@ ScMatrixRef FormulaGroupInterpreterOpenCL::inverseMatrix(const ScMatrix& /* rMat
bool FormulaGroupInterpreterOpenCL::interpret(ScDocument& rDoc, const ScAddress& rTopPos,
const ScFormulaCellGroupRef& xGroup, ScTokenArray& rCode)
{
+ generateRPNCode(rDoc, rTopPos, rCode);
+
size_t rowSize = xGroup->mnLength;
fprintf(stderr,"rowSize at begin is ...%ld.\n",(long)rowSize);
// The row quantity can be gotten from p2->GetArrayLength()
@@ -193,9 +195,7 @@ bool FormulaGroupInterpreterOpenCL::interpret(ScDocument& rDoc, const ScAddress&
if(!getenv("SC_GPU")||!ocl_calc.GetOpenclState())
{
fprintf(stderr,"ccCPU flow...\n\n");
- ScCompiler aComp(&rDoc, aTmpPos, aCode2);
- aComp.SetGrammar(rDoc.GetGrammar());
- aComp.CompileTokenArray(); // Create RPN token array.
+ generateRPNCode(rDoc, aTmpPos, aCode2);
ScInterpreter aInterpreter(pDest, &rDoc, aTmpPos, aCode2);
aInterpreter.Interpret();
pDest->SetResultToken(aInterpreter.GetResultToken().get());
@@ -306,6 +306,8 @@ bool FormulaGroupInterpreterGroundwater::interpret(ScDocument& rDoc, const ScAdd
const ScFormulaCellGroupRef& xGroup,
ScTokenArray& rCode)
{
+ generateRPNCode(rDoc, rTopPos, rCode);
+
// Inputs: both of length xGroup->mnLength
OpCode eOp; // type of operation: ocAverage, ocMax, ocMin
const double *pArrayToSubtractOneElementFrom;
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index 627c5f5..5a23511 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -96,9 +96,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
if (!pDest)
return false;
- ScCompiler aComp(&rDoc, aTmpPos, aCode2);
- aComp.SetGrammar(rDoc.GetGrammar());
- aComp.CompileTokenArray(); // Create RPN token array.
+ generateRPNCode(rDoc, aTmpPos, aCode2);
ScInterpreter aInterpreter(pDest, &rDoc, aTmpPos, aCode2);
aInterpreter.Interpret();
aResults.push_back(aInterpreter.GetResultToken()->GetDouble());
@@ -190,6 +188,15 @@ FormulaGroupInterpreter *FormulaGroupInterpreter::getStatic()
return msInstance;
}
+void FormulaGroupInterpreter::generateRPNCode(ScDocument& rDoc, const ScAddress& rPos, ScTokenArray& rCode)
+{
+ // First, generate an RPN (reverse polish notation) token array.
+ ScCompiler aComp(&rDoc, rPos, rCode);
+ aComp.SetGrammar(rDoc.GetGrammar());
+ aComp.CompileTokenArray(); // Create RPN token array.
+ // Now, calling FirstRPN() and NextRPN() will return tokens from the RPN token array.
+}
+
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 9ed6e520afb8905596cd382e1e7fa79ba20063b5
Author: Michael Meeks <michael.meeks at suse.com>
Date: Tue Jul 9 12:02:43 2013 +0100
better opencl error reporting / diagnostics.
diff --git a/sc/source/core/opencl/openclwrapper.cxx b/sc/source/core/opencl/openclwrapper.cxx
index 31f1589..0c94721 100755
--- a/sc/source/core/opencl/openclwrapper.cxx
+++ b/sc/source/core/opencl/openclwrapper.cxx
@@ -2131,6 +2131,7 @@ double *OclCalc::OclSimpleDeltaOperation(OpCode eOp, const double *pOpArray,
size_t global_work_size[1];
kEnv.mpkKernel = clCreateKernel(kEnv.mpkProgram,kernelName, &clStatus);
+ CHECK_OPENCL(clStatus);
// Ugh - horrible redundant copying ...
cl_mem valuesCl = allocateDoubleBuffer(kEnv, pOpArray, nElements, &clStatus);
@@ -2147,12 +2148,16 @@ double *OclCalc::OclSimpleDeltaOperation(OpCode eOp, const double *pOpArray,
clStatus = clSetKernelArg(kEnv.mpkKernel, 0, sizeof(cl_mem),
(void *)&valuesCl);
+ CHECK_OPENCL(clStatus);
clStatus = clSetKernelArg(kEnv.mpkKernel, 1, sizeof(cl_mem),
(void *)&subtractCl);
- clStatus = clSetKernelArg(kEnv.mpkKernel, 2, sizeof(cl_mem),
+ CHECK_OPENCL(clStatus);
+ clStatus = clSetKernelArg(kEnv.mpkKernel, 2, sizeof(cl_int),
(void *)&start);
- clStatus = clSetKernelArg(kEnv.mpkKernel, 3, sizeof(cl_mem),
+ CHECK_OPENCL(clStatus);
+ clStatus = clSetKernelArg(kEnv.mpkKernel, 3, sizeof(cl_int),
(void *)&end);
+ CHECK_OPENCL(clStatus);
clStatus = clSetKernelArg(kEnv.mpkKernel, 4, sizeof(cl_mem),
(void *)&outputCl);
CHECK_OPENCL(clStatus);
diff --git a/sc/source/core/opencl/openclwrapper.hxx b/sc/source/core/opencl/openclwrapper.hxx
index a0c132a..fe62554 100755
--- a/sc/source/core/opencl/openclwrapper.hxx
+++ b/sc/source/core/opencl/openclwrapper.hxx
@@ -12,6 +12,7 @@
#include <config_features.h>
#include <formula/opcode.hxx>
+#include <sal/detail/log.h>
#include <cassert>
#include <CL/cl.h>
#endif
@@ -55,7 +56,7 @@ typedef int (*cl_kernel_function)(void **userdata, KernelEnv *kenv);
#define CHECK_OPENCL(status) \
if(status != CL_SUCCESS) \
{ \
- printf ("error code is %d.\n",status); \
+ printf ("OpenCL error code is %d at " SAL_DETAIL_WHERE "\n", status); \
return 0; \
}
commit 98e811e43209faced8e8144267ded2032d44f4bc
Author: Michael Meeks <michael.meeks at suse.com>
Date: Mon Jul 8 21:49:31 2013 +0100
try harder to setup the kernel environment.
diff --git a/sc/source/core/opencl/openclwrapper.cxx b/sc/source/core/opencl/openclwrapper.cxx
index 3030a2e..31f1589 100755
--- a/sc/source/core/opencl/openclwrapper.cxx
+++ b/sc/source/core/opencl/openclwrapper.cxx
@@ -2111,6 +2111,7 @@ double *OclCalc::OclSimpleDeltaOperation(OpCode eOp, const double *pOpArray,
const double *pSubtractSingle, size_t nElements)
{
KernelEnv kEnv;
+ SetKernelEnv(&kEnv);
// select a kernel: cut & paste coding is utterly evil.
const char *kernelName;
commit c6fd693a8a1efb9e301bd623d29411dfa2378e5c
Author: Michael Meeks <michael.meeks at suse.com>
Date: Mon Jul 8 21:35:26 2013 +0100
cleanup formulagroupcl and add opencl kernel for averagedelta.
Conflicts:
sc/source/core/opencl/openclwrapper.hxx
Change-Id: Id4777d3854d34ab34dd29b050cd329a803023a39
diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx
index d92a471..8bc0224 100755
--- a/sc/source/core/opencl/formulagroupcl.cxx
+++ b/sc/source/core/opencl/formulagroupcl.cxx
@@ -310,11 +310,8 @@ bool FormulaGroupInterpreterGroundwater::interpret(ScDocument& rDoc, const ScAdd
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;
@@ -338,36 +335,13 @@ bool FormulaGroupInterpreterGroundwater::interpret(ScDocument& rDoc, const ScAdd
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();
- }
+ RETURN_IF_FAIL(p->GetType() == formula::svDoubleVectorRef, "wrong type of fn argument");
+ 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];
p = rCode.NextNoSpaces();
RETURN_IF_FAIL(p != NULL && p->GetOpCode() == ocClose, "missing closing )");
@@ -400,17 +374,22 @@ bool FormulaGroupInterpreterGroundwater::interpret(ScDocument& rDoc, const ScAdd
// =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)
+ // pGroundWaterDataArray => contains L$5:L$7701
+ // pArrayToSubtractOneElementFrom => contains L$5:L$7701 (ie. a copy)
// length of this array -> xGroup->mnLength
fprintf (stderr, "Calculate !\n");
+ double *pResult = ocl_calc.OclSimpleDeltaOperation( eOp, pGroundWaterDataArray,
+ pArrayToSubtractOneElementFrom,
+ (size_t) xGroup->mnLength );
+ RETURN_IF_FAIL(pResult != NULL, "buffer alloc / calculaton failed");
+
// 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;
}
diff --git a/sc/source/core/opencl/oclkernels.hxx b/sc/source/core/opencl/oclkernels.hxx
index 6c90126..e13c24a 100755
--- a/sc/source/core/opencl/oclkernels.hxx
+++ b/sc/source/core/opencl/oclkernels.hxx
@@ -142,7 +142,6 @@ __kernel void oclFormulaAverage(__global float *input,__global int *start,__glob
for(i = start[id];i<=end[id];i++)
sum += input[i];
output[id] = sum / (end[id]-start[id]+1);
-
}
//Sumproduct
@@ -162,6 +161,33 @@ __kernel void oclFormulaMinverse(__global float *data,
}
+// Double precision is a requirement of spreadsheets
+#if 0
+#if defined(cl_khr_fp64) // Khronos extension
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+#elif defined(cl_amd_fp64) // AMD extension
+#pragma OPENCL EXTENSION cl_amd_fp64 : enable
+#endif
+typedef double fp_t;
+#else
+typedef float fp_t;
+#endif
+
+__kernel void oclAverageDelta(__global fp_t *values, __global fp_t *subtract, __global int start, __global int end, __global fp_t *output)
+{
+ const unsigned int id = get_global_id(0);
+
+ // Average
+ int i;
+ fp_t sum = 0.0;
+ for(i = start; i < end; i++)
+ sum += values[i];
+ fp_t val = sum/(end-start);
+
+ // Subtract & output
+ output[id] = val - subtract[id];
+}
+
);
#endif // USE_EXTERNAL_KERNEL
diff --git a/sc/source/core/opencl/openclwrapper.cxx b/sc/source/core/opencl/openclwrapper.cxx
index 597f370..3030a2e 100755
--- a/sc/source/core/opencl/openclwrapper.cxx
+++ b/sc/source/core/opencl/openclwrapper.cxx
@@ -76,16 +76,17 @@ int OpenclDevice::ReleaseOpenclRunEnv() {
}
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
-inline int OpenclDevice::AddKernelConfig(int kCount, const char *kName) {
+inline int OpenclDevice::AddKernelConfig(int kCount, const char *kName)
+{
strcpy(gpuEnv.mArrykernelNames[kCount], kName);
gpuEnv.mnKernelCount++;
return 0;
}
-int OpenclDevice::RegistOpenclKernel() {
- if (!gpuEnv.mnIsUserCreated) {
+int OpenclDevice::RegistOpenclKernel()
+{
+ if (!gpuEnv.mnIsUserCreated)
memset(&gpuEnv, 0, sizeof(gpuEnv));
- }
gpuEnv.mnFileCount = 0; //argc;
gpuEnv.mnKernelCount = 0UL;
@@ -100,17 +101,22 @@ int OpenclDevice::RegistOpenclKernel() {
AddKernelConfig(7, (const char*) "oclFormulaSumproduct");
AddKernelConfig(8, (const char*) "oclFormulaMinverse");
- AddKernelConfig(9, (const char*) "oclSignedAdd");
+ AddKernelConfig(9, (const char*) "oclSignedAdd");
AddKernelConfig(10, (const char*) "oclSignedSub");
AddKernelConfig(11, (const char*) "oclSignedMul");
AddKernelConfig(12, (const char*) "oclSignedDiv");
+ AddKernelConfig(13, (const char*) "oclAverageDelta");
+
return 0;
}
-OpenclDevice::OpenclDevice(){
+
+OpenclDevice::OpenclDevice()
+{
//InitEnv();
}
-OpenclDevice::~OpenclDevice() {
+OpenclDevice::~OpenclDevice()
+{
//ReleaseOpenclRunEnv();
}
@@ -122,13 +128,15 @@ int OpenclDevice::SetKernelEnv(KernelEnv *envInfo)
return 1;
}
-int OpenclDevice::CheckKernelName(KernelEnv *envInfo,const char *kernelName){
+
+int OpenclDevice::CheckKernelName(KernelEnv *envInfo,const char *kernelName)
+{
//printf("CheckKernelName,total count of kernels...%d\n", gpuEnv.kernelCount);
int kCount;
for(kCount=0; kCount < gpuEnv.mnKernelCount; kCount++) {
if(strcasecmp(kernelName, gpuEnv.mArrykernelNames[kCount]) == 0) {
- printf("match %s kernel right\n",kernelName);
- break;
+ printf("match %s kernel right\n",kernelName);
+ break;
}
}
envInfo->mpkKernel = gpuEnv.mpArryKernels[kCount];
@@ -141,7 +149,8 @@ int OpenclDevice::CheckKernelName(KernelEnv *envInfo,const char *kernelName){
return 1;
}
-int OpenclDevice::ConvertToString(const char *filename, char **source) {
+int OpenclDevice::ConvertToString(const char *filename, char **source)
+{
int file_size;
size_t result;
FILE *file = NULL;
@@ -174,8 +183,9 @@ int OpenclDevice::ConvertToString(const char *filename, char **source) {
return 0;
}
-int OpenclDevice::BinaryGenerated(const char * clFileName, FILE ** fhandle) {
- unsigned int i = 0;
+int OpenclDevice::BinaryGenerated(const char * clFileName, FILE ** fhandle)
+{
+ unsigned int i = 0;
cl_int status;
char *str = NULL;
FILE *fd = NULL;
@@ -208,7 +218,8 @@ int OpenclDevice::BinaryGenerated(const char * clFileName, FILE ** fhandle) {
}
int OpenclDevice::WriteBinaryToFile(const char* fileName, const char* birary,
- size_t numBytes) {
+ size_t numBytes)
+{
FILE *output = NULL;
output = fopen(fileName, "wb");
if (output == NULL) {
@@ -223,7 +234,8 @@ int OpenclDevice::WriteBinaryToFile(const char* fileName, const char* birary,
}
int OpenclDevice::GeneratBinFromKernelSource(cl_program program,
- const char * clFileName) {
+ const char * clFileName)
+{
unsigned int i = 0;
cl_int status;
size_t *binarySizes, numDevices;
@@ -319,10 +331,10 @@ int OpenclDevice::GeneratBinFromKernelSource(cl_program program,
return 1;
}
-int OpenclDevice::InitOpenclAttr(OpenCLEnv * env) {
- if (gpuEnv.mnIsUserCreated) {
+int OpenclDevice::InitOpenclAttr(OpenCLEnv * env)
+{
+ if (gpuEnv.mnIsUserCreated)
return 1;
- }
gpuEnv.mpContext = env->mpOclContext;
gpuEnv.mpPlatformID = env->mpOclPlatformID;
@@ -334,21 +346,24 @@ int OpenclDevice::InitOpenclAttr(OpenCLEnv * env) {
return 0;
}
-int OpenclDevice::CreateKernel(char * kernelname, KernelEnv * env) {
+int OpenclDevice::CreateKernel(char * kernelname, KernelEnv * env)
+{
int status;
- env->mpkKernel = clCreateKernel(gpuEnv.mpArryPrograms[0], kernelname, &status);
+ env->mpkKernel = clCreateKernel(gpuEnv.mpArryPrograms[0], kernelname, &status);
env->mpkContext = gpuEnv.mpContext;
env->mpkCmdQueue = gpuEnv.mpCmdQueue;
return status != CL_SUCCESS ? 1 : 0;
}
-int OpenclDevice::ReleaseKernel(KernelEnv * env) {
+int OpenclDevice::ReleaseKernel(KernelEnv * env)
+{
int status = clReleaseKernel(env->mpkKernel);
return status != CL_SUCCESS ? 1 : 0;
}
-int OpenclDevice::ReleaseOpenclEnv(GPUEnv *gpuInfo) {
+int OpenclDevice::ReleaseOpenclEnv(GPUEnv *gpuInfo)
+{
int i = 0;
int status = 0;
@@ -378,7 +393,8 @@ int OpenclDevice::ReleaseOpenclEnv(GPUEnv *gpuInfo) {
}
int OpenclDevice::RunKernelWrapper(cl_kernel_function function,
- const char * kernelName, void **usrdata) {
+ const char * kernelName, void **usrdata)
+{
printf("oclwrapper:RunKernel_wrapper...\n");
if (RegisterKernelWrapper(kernelName, function) != 1) {
fprintf(stderr,
@@ -389,8 +405,9 @@ int OpenclDevice::RunKernelWrapper(cl_kernel_function function,
}
int OpenclDevice::CachedOfKernerPrg(const GPUEnv *gpuEnvCached,
- const char * clFileName) {
- int i;
+ const char * clFileName)
+{
+ int i;
for (i = 0; i < gpuEnvCached->mnFileCount; i++) {
if (strcasecmp(gpuEnvCached->mArryKnelSrcFile[i], clFileName) == 0) {
if (gpuEnvCached->mpArryPrograms[i] != NULL) {
@@ -574,6 +591,7 @@ int OpenclDevice::RunKernel(const char *kernelName, void **userdata) {
}
return 0;
}
+
int OpenclDevice::InitOpenclRunEnv(int argc, const char *buildOptionKernelfiles)
{
int status = 0;
@@ -1007,6 +1025,7 @@ int OclCalc::OclHostFormulaMax(double *srcData,int *start,int *end,double *outpu
CHECK_OPENCL(clStatus);
return 0;
}
+
int OclCalc::OclHostFormulaMin(double *srcData,int *start,int *end,double *output,int size)
{
KernelEnv kEnv;
@@ -1590,7 +1609,6 @@ int OclCalc::OclHostFormulaMin32Bits(float *fpSrcData,uint *npStartPos,uint *npE
clStatus = clReleaseMemObject(outputCl);
CHECK_OPENCL(clStatus);
return 0;
-
}
int OclCalc::OclHostFormulaAverage32Bits(float *fpSrcData,uint *npStartPos,uint *npEndPos,double *output,int size)
@@ -2066,4 +2084,111 @@ int OclCalc::OclHostFormulaSumProduct(float *dpSrcData,int *npStart,int *npEnd,f
}
#endif
+#if 0
+typedef double fp_;
+#else
+typedef float fp_t;
+#endif
+
+// FIXME: should be templatised in <double> - double buffering [sic] rocks
+static cl_mem allocateDoubleBuffer(KernelEnv &rEnv, const double *_pValues,
+ size_t nElements, cl_int *pStatus)
+{
+ // Ugh - horrible redundant copying ...
+ cl_mem xValues = clCreateBuffer(rEnv.mpkContext,(cl_mem_flags) (CL_MEM_READ_WRITE),
+ nElements * sizeof(double), NULL, pStatus);
+ fp_t *pValues = (fp_t *)clEnqueueMapBuffer(rEnv.mpkCmdQueue,xValues,CL_TRUE,CL_MAP_WRITE,0,
+ nElements * sizeof(fp_t),0,NULL,NULL,NULL);
+ for(int i=0;i<nElements;i++)
+ pValues[i] = (fp_t)_pValues[i];
+
+ clEnqueueUnmapMemObject(rEnv.mpkCmdQueue,xValues,pValues,0,NULL,NULL);
+
+ return xValues;
+}
+
+double *OclCalc::OclSimpleDeltaOperation(OpCode eOp, const double *pOpArray,
+ const double *pSubtractSingle, size_t nElements)
+{
+ KernelEnv kEnv;
+
+ // select a kernel: cut & paste coding is utterly evil.
+ const char *kernelName;
+ switch (eOp) {
+ case ocMax:
+ case ocMin:
+ ; // FIXME: fallthrough for now
+ case ocAverage:
+ kernelName = "oclAverageDelta";
+ break;
+ default:
+ assert(false);
+ }
+ CheckKernelName(&kEnv,kernelName);
+
+ cl_int clStatus;
+ size_t global_work_size[1];
+
+ kEnv.mpkKernel = clCreateKernel(kEnv.mpkProgram,kernelName, &clStatus);
+
+ // Ugh - horrible redundant copying ...
+ cl_mem valuesCl = allocateDoubleBuffer(kEnv, pOpArray, nElements, &clStatus);
+ cl_mem subtractCl = allocateDoubleBuffer(kEnv, pSubtractSingle, nElements, &clStatus);
+
+ cl_int start = 0;
+ cl_int end = (cl_int) nElements;
+ cl_mem outputCl = clCreateBuffer(kEnv.mpkContext,
+ CL_MEM_READ_WRITE,
+ nElements * sizeof(fp_t),
+ NULL,
+ &clStatus);
+ CHECK_OPENCL(clStatus);
+
+ clStatus = clSetKernelArg(kEnv.mpkKernel, 0, sizeof(cl_mem),
+ (void *)&valuesCl);
+ clStatus = clSetKernelArg(kEnv.mpkKernel, 1, sizeof(cl_mem),
+ (void *)&subtractCl);
+ clStatus = clSetKernelArg(kEnv.mpkKernel, 2, sizeof(cl_mem),
+ (void *)&start);
+ clStatus = clSetKernelArg(kEnv.mpkKernel, 3, sizeof(cl_mem),
+ (void *)&end);
+ clStatus = clSetKernelArg(kEnv.mpkKernel, 4, sizeof(cl_mem),
+ (void *)&outputCl);
+ CHECK_OPENCL(clStatus);
+
+ fprintf(stderr, "prior to enqueue range kernel\n");
+
+ global_work_size[0] = nElements;
+ clStatus = clEnqueueNDRangeKernel(kEnv.mpkCmdQueue, kEnv.mpkKernel, 1,
+ NULL, global_work_size, NULL, 0, NULL, NULL);
+ CHECK_OPENCL(clStatus);
+
+ double *pResult = new double[nElements];
+ if(!pResult)
+ return NULL; // leak.
+
+ fp_t *pOutput = (fp_t *)clEnqueueMapBuffer(kEnv.mpkCmdQueue,outputCl,CL_TRUE,
+ CL_MAP_READ,0,nElements*sizeof(fp_t),
+ 0,NULL,NULL,NULL);
+ for(int i = 0; i < nElements; i++)
+ pResult[i] = (double)pOutput[i];
+
+ clEnqueueUnmapMemObject(kEnv.mpkCmdQueue,outputCl,pOutput,0,NULL,NULL);
+
+ clStatus = clFinish(kEnv.mpkCmdQueue);
+ CHECK_OPENCL(clStatus);
+ clStatus = clReleaseKernel(kEnv.mpkKernel);
+ CHECK_OPENCL(clStatus);
+ clStatus = clReleaseMemObject(valuesCl);
+ CHECK_OPENCL(clStatus);
+ clStatus = clReleaseMemObject(subtractCl);
+ CHECK_OPENCL(clStatus);
+ clStatus = clReleaseMemObject(outputCl);
+ CHECK_OPENCL(clStatus);
+
+ fprintf(stderr, "completed opencl delta operation\n");
+
+ return pResult;
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/opencl/openclwrapper.hxx b/sc/source/core/opencl/openclwrapper.hxx
index 3e87f84..a0c132a 100755
--- a/sc/source/core/opencl/openclwrapper.hxx
+++ b/sc/source/core/opencl/openclwrapper.hxx
@@ -11,10 +11,8 @@
#define _OPENCL_WRAPPER_H_
#include <config_features.h>
-
-#ifdef __APPLE__
-#include <OpenCL/cl.h>
-#else
+#include <formula/opcode.hxx>
+#include <cassert>
#include <CL/cl.h>
#endif
@@ -212,6 +210,7 @@ public:
int OclHostFormulaMax32Bits(float *fpSrcData,uint *npStartPos,uint *npEndPos,double *output,int outputSize);
int OclHostFormulaMin32Bits(float *fpSrcData,uint *npStartPos,uint *npEndPos,double *output,int outputSize);
int OclHostFormulaAverage32Bits(float *fpSrcData,uint *npStartPos,uint *npEndPos,double *output,int outputSize);
+ double *OclSimpleDeltaOperation(OpCode eOp, const double *pOpArray, const double *pSubtractSingle, size_t nElements);
//int OclHostFormulaCount(int *startPos,int *endPos,float *output,int outputSize);
//int OclHostFormulaSum(float *srcData,int *startPos,int *endPos,float *output,int outputSize);
commit d5ae61ed2394b6945b969c61aea0adac2234f702
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 17653c9..55f5010 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 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 e67ae6c1ca5d0df2fb3b94dda32519288225fb30
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;
}
commit d05ec5563621f0b51757dd42737565d29fbadd2b
Author: Michael Meeks <michael.meeks at suse.com>
Date: Mon Jul 8 10:49:05 2013 +0100
Latest cleanup and improvements of opencl backend.
Conflicts:
sc/source/core/opencl/openclwrapper.cxx
Change-Id: I3fdc90570e90a156ccecb511fc04b473752018bd
diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx
old mode 100644
new mode 100755
index 6a96129..857f045
--- a/sc/source/core/opencl/formulagroupcl.cxx
+++ b/sc/source/core/opencl/formulagroupcl.cxx
@@ -65,35 +65,32 @@ ScMatrixRef FormulaGroupInterpreterOpenCL::inverseMatrix(const ScMatrix& /* rMat
bool FormulaGroupInterpreterOpenCL::interpret(ScDocument& rDoc, const ScAddress& rTopPos,
const ScFormulaCellGroupRef& xGroup, ScTokenArray& rCode)
{
- size_t rowSize = xGroup->mnLength; //, srcSize = 0;
+ size_t rowSize = xGroup->mnLength;
fprintf(stderr,"rowSize at begin is ...%ld.\n",(long)rowSize);
- int *rangeStart =NULL; // The first position for calculation,for example,the A1 in (=MAX(A1:A100))
- int *rangeEnd = NULL; // The last position for calculation,for example, the A100 in (=MAX(A1:A100))
// The row quantity can be gotten from p2->GetArrayLength()
- int count1 =0,count2 =0,count3=0;
- int oclOp=0;
- double *srcData = NULL; // Point to the input data from CPU
- double *rResult=NULL; // Point to the output data from GPU
- double *leftData=NULL; // Left input for binary operator(+,-,*,/),for example,(=leftData+rightData)
- double *rightData=NULL; // Right input for binary operator(+,-,*,/),for example,(=leftData/rightData)
- // The rightData can't be zero for "/"
-
- leftData = (double *)malloc(sizeof(double) * rowSize);
- rightData = (double *)malloc(sizeof(double) * rowSize);
- rResult = (double *)malloc(sizeof(double) * rowSize*2);// For 2 columns(B,C)
- srcData = (double *)calloc(rowSize,sizeof(double));
-
- rangeStart =(int *)malloc(sizeof(int) * rowSize);
- rangeEnd =(int *)malloc(sizeof(int) * rowSize);
-
- memset(rResult,0,rowSize);
- if(NULL==leftData||NULL==rightData||
- NULL==rResult||NULL==rangeStart||NULL==rangeEnd)
+ int nCount1 = 0, nCount2 = 0, nCount3 = 0;
+ int nOclOp = 0;
+ double *rResult = NULL; // Point to the output data from GPU
+ rResult = (double *)malloc(sizeof(double) * rowSize*2);// For 2 columns(B,C)
+ if(NULL==rResult)
{
printf("malloc err\n");
return false;
}
- // printf("rowSize is %d.\n",rowsize);
+ memset(rResult,0,rowSize);
+ float * fpOclSrcData = NULL; // Point to the input data from CPU
+ uint * npOclStartPos = NULL; // The first position for calculation,for example,the A1 in (=MAX(A1:A100))
+ uint * npOclEndPos = NULL; // The last position for calculation,for example, the A100 in (=MAX(A1:A100))
+ float * fpLeftData = NULL; // Left input for binary operator(+,-,*,/),for example,(=leftData+rightData)
+ float * fpRightData = NULL; // Right input for binary operator(+,-,*,/),for example,(=leftData/rightData)
+ // The rightData can't be zero for "/"
+ static OclCalc ocl_calc;
+ // Don't know how large the size will be applied previously, so create them as the rowSize or 65536
+ // Don't know which formulae will be used previously, so create buffers for different formulae used probably
+ ocl_calc.CreateBuffer(fpOclSrcData,npOclStartPos,npOclEndPos,rowSize);
+ ocl_calc.CreateBuffer(fpLeftData,fpRightData,rowSize);
+ //printf("pptrr is %d,%d,%d\n",fpOclSrcData,npOclStartPos,npOclEndPos);
+///////////////////////////////////////////////////////////////////////////////////////////
// Until we implement group calculation for real, decompose the group into
// individual formula token arrays for individual calculation.
@@ -125,26 +122,23 @@ bool FormulaGroupInterpreterOpenCL::interpret(ScDocument& rDoc, const ScAddress&
size_t nRowSize = nRowEnd - nRowStart + 1;
ScMatrixRef pMat(new ScMatrix(nColSize, nRowSize, 0.0));
- //srcSize = rowSize+nRowSize-rowSize%nRowSize;//align as nRowSize
- //srcData = (double *)calloc(srcSize,sizeof(double));
- rangeStart[i] = nRowStart;//record the start position
- rangeEnd[i] = nRowEnd;//record the end position
+ npOclStartPos[i] = nRowStart; // record the start position
+ npOclEndPos[i] = nRowEnd; // record the end position
for (size_t nCol = 0; nCol < nColSize; ++nCol)
{
const double* pArray = rArrays[nCol];
-
- //printf("pArray is %p.\n",pArray);
if( NULL==pArray )
{
fprintf(stderr,"Error: pArray is NULL!\n");
return false;
}
- //fprintf(stderr,"(rowSize+nRowSize-1) is %d.\n",rowSize+nRowSize-1);
+
for( size_t u=0; u<rowSize; u++ )
{
- srcData[u] = pArray[u];// note:rowSize<=srcSize
- //fprintf(stderr,"srcData[%d] is %f.\n",u,srcData[u]);
+ // Many video cards can't support double type in kernel, so need transfer the double to float
+ fpOclSrcData[u] = (float)pArray[u];
+ //fprintf(stderr,"fpOclSrcData[%d] is %f.\n",u,fpOclSrcData[u]);
}
for (size_t nRow = 0; nRow < nRowSize; ++nRow)
@@ -177,26 +171,26 @@ bool FormulaGroupInterpreterOpenCL::interpret(ScDocument& rDoc, const ScAddress&
OpCode eOp = pCur->GetOpCode();
if(eOp==0)
{
- if(count3%2==0)
- leftData[count1++] = pCur->GetDouble();
- else
- rightData[count2++] = pCur->GetDouble();
- count3++;
- }
- else if( eOp!=ocOpen && eOp!=ocClose )
- oclOp = eOp;
-
-// if(count1>0){//dbg
-// fprintf(stderr,"leftData is %f.\n",leftData[count1-1]);
-// count1--;
-// }
-// if(count2>0){//dbg
-// fprintf(stderr,"rightData is %f.\n",rightData[count2-1]);
-// count2--;
-// }
+ if(nCount3%2==0)
+ fpLeftData[nCount1++] = (float)pCur->GetDouble();
+ else
+ fpRightData[nCount2++] = (float)pCur->GetDouble();
+ nCount3++;
+ }
+ else if( eOp!=ocOpen && eOp!=ocClose )
+ nOclOp = eOp;
+
+// if(count1>0){//dbg
+// fprintf(stderr,"leftData is %f.\n",leftData[count1-1]);
+// count1--;
+// }
+// if(count2>0){//dbg
+// fprintf(stderr,"rightData is %f.\n",rightData[count2-1]);
+// count2--;
+// }
}
- if(!getenv("SC_GPU"))
+ if(!getenv("SC_GPU")||!ocl_calc.GetOpenclState())
{
fprintf(stderr,"ccCPU flow...\n\n");
ScCompiler aComp(&rDoc, aTmpPos, aCode2);
@@ -211,34 +205,42 @@ bool FormulaGroupInterpreterOpenCL::interpret(ScDocument& rDoc, const ScAddress&
} // for loop end (xGroup->mnLength)
// For GPU calculation
- if(getenv("SC_GPU"))
+ if(getenv("SC_GPU")&&ocl_calc.GetOpenclState())
{
fprintf(stderr,"ggGPU flow...\n\n");
- printf(" oclOp is... %d\n",oclOp);
+ printf(" oclOp is... %d\n",nOclOp);
osl_getSystemTime(&aTimeBefore); //timer
- static OclCalc ocl_calc;
- switch(oclOp)
+ switch(nOclOp)
{
case ocAdd:
- ocl_calc.OclHostSignedAdd(leftData,rightData,rResult,count1);
+ ocl_calc.OclHostSignedAdd32Bits(fpLeftData,fpRightData,rResult,nCount1);
break;
case ocSub:
- ocl_calc.OclHostSignedSub(leftData,rightData,rResult,count1);
+ ocl_calc.OclHostSignedSub32Bits(fpLeftData,fpRightData,rResult,nCount1);
break;
case ocMul:
- ocl_calc.OclHostSignedMul(leftData,rightData,rResult,count1);
+ ocl_calc.OclHostSignedMul32Bits(fpLeftData,fpRightData,rResult,nCount1);
break;
case ocDiv:
- ocl_calc.OclHostSignedDiv(leftData,rightData,rResult,count1);
+ ocl_calc.OclHostSignedDiv32Bits(fpLeftData,fpRightData,rResult,nCount1);
break;
case ocMax:
- ocl_calc.OclHostFormulaMax(srcData,rangeStart,rangeEnd,rResult,rowSize);
+ ocl_calc.OclHostFormulaMax32Bits(fpOclSrcData,npOclStartPos,npOclEndPos,rResult,rowSize);
break;
case ocMin:
- ocl_calc.OclHostFormulaMin(srcData,rangeStart,rangeEnd,rResult,rowSize);
+ ocl_calc.OclHostFormulaMin32Bits(fpOclSrcData,npOclStartPos,npOclEndPos,rResult,rowSize);
break;
case ocAverage:
- ocl_calc.OclHostFormulaAverage(srcData,rangeStart,rangeEnd,rResult,rowSize);
+ ocl_calc.OclHostFormulaAverage32Bits(fpOclSrcData,npOclStartPos,npOclEndPos,rResult,rowSize);
+ break;
+ case ocSum:
+ //ocl_calc.OclHostFormulaSum(srcData,rangeStart,rangeEnd,rResult,rowSize);
+ break;
+ case ocCount:
+ //ocl_calc.OclHostFormulaCount(rangeStart,rangeEnd,rResult,rowSize);
+ break;
+ case ocSumProduct:
+ //ocl_calc.OclHostFormulaSumProduct(srcData,rangeStart,rangeEnd,rResult,rowSize);
break;
default:
fprintf(stderr,"No OpenCL function for this calculation.\n");
@@ -254,26 +256,16 @@ bool FormulaGroupInterpreterOpenCL::interpret(ScDocument& rDoc, const ScAddress&
/////////////////////////////////////////////////////
//rResult[i];
-// for(sal_Int32 i = 0; i < rowSize; ++i){//dbg output results
-// fprintf(stderr,"After GPU,rRsults[%d] is ...%f\n",i,rResult[i]);
-// }
+// for(sal_Int32 i = 0; i < rowSize; ++i){//dbg output results
+// fprintf(stderr,"After GPU,rRsults[%d] is ...%f\n",i,rResult[i]);
+// }
// Insert the double data, in rResult[i] back into the document
rDoc.SetFormulaResults(rTopPos, rResult, xGroup->mnLength);
}
- if(leftData)
- free(leftData);
- if(rightData)
- free(rightData);
- if(rangeStart)
- free(rangeStart);
- if(rangeEnd)
- free(rangeEnd);
if(rResult)
free(rResult);
- if(srcData)
- free(srcData);
if(getenv("SC_GPUSAMPLE")){
//fprintf(stderr,"FormulaGroupInterpreter::interpret(),iniflag...%d\n",ocl_calc.GetOpenclState());
diff --git a/sc/source/core/opencl/oclkernels.hxx b/sc/source/core/opencl/oclkernels.hxx
old mode 100644
new mode 100755
index 3269f3a..6c90126
--- a/sc/source/core/opencl/oclkernels.hxx
+++ b/sc/source/core/opencl/oclkernels.hxx
@@ -6,153 +6,158 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
+
#ifndef _OCL_KERNEL_H_
#define _OCL_KERNEL_H_
#ifndef USE_EXTERNAL_KERNEL
#define KERNEL( ... )# __VA_ARGS__
-
/////////////////////////////////////////////
const char *kernel_src = KERNEL(
__kernel void hello(__global uint *buffer)
{
-size_t idx = get_global_id(0);
-
-buffer[idx]=idx;
-
+ size_t idx = get_global_id(0);
+ buffer[idx]=idx;
}
__kernel void oclformula(__global float *data,
- const uint type)
+ const uint type)
{
- const unsigned int i = get_global_id(0);
-
- switch (type)
- {
- case 0: //MAX
- {
- //printf("%i ?%f>%f\n",i,data[2*i],data[2*i+1]);
- if(data[2*i]>data[2*i+1])
- data[i] = data[2*i];
- else
- data[i] = data[2*i+1];
- break;
- }
- case 1: //MIN
- {
- //printf("%d ?%d<%d\n",i,data[2*i],data[2*i+1]);
- if(data[2*i]<data[2*i+1])
- data[i] = data[2*i];
- else
- data[i] = data[2*i+1];
- break;
- }
- case 2: //SUM
- case 3: //AVG
- {
- //printf("%d %d+%d\n",i,data[2*i],data[2*i+1]);
- data[i] = data[2*i] + data[2*i+1];
- break;
- }
- default:
- break;
-
- }
+ const unsigned int i = get_global_id(0);
+
+ switch (type)
+ {
+ case 0: //MAX
+ {
+ //printf("%i ?%f>%f\n",i,data[2*i],data[2*i+1]);
+ if(data[2*i]>data[2*i+1])
+ data[i] = data[2*i];
+ else
+ data[i] = data[2*i+1];
+ break;
+ }
+ case 1: //MIN
+ {
+ //printf("%d ?%d<%d\n",i,data[2*i],data[2*i+1]);
+ if(data[2*i]<data[2*i+1])
+ data[i] = data[2*i];
+ else
+ data[i] = data[2*i+1];
+ break;
+ }
+ case 2: //SUM
+ case 3: //AVG
+ {
+ //printf("%d %d+%d\n",i,data[2*i],data[2*i+1]);
+ data[i] = data[2*i] + data[2*i+1];
+ break;
+ }
+ default:
+ break;
+
+ }
}
__kernel void oclSignedAdd(__global float *ltData,__global float *rtData,__global float *otData)
{
- const unsigned int id = get_global_id(0);
- otData[id] = ltData[id] + rtData[id];
+ const unsigned int id = get_global_id(0);
+ otData[id] = ltData[id] + rtData[id];
}
__kernel void oclSignedSub(__global float *ltData,__global float *rtData,__global float *otData)
{
- const unsigned int id = get_global_id(0);
- otData[id] = ltData[id] - rtData[id];
+ const unsigned int id = get_global_id(0);
+ otData[id] = ltData[id] - rtData[id];
}
__kernel void oclSignedMul(__global float *ltData,__global float *rtData,__global float *otData)
{
- int id = get_global_id(0);
- otData[id] =ltData[id] * rtData[id];
+ int id = get_global_id(0);
+ otData[id] =ltData[id] * rtData[id];
}
__kernel void oclSignedDiv(__global float *ltData,__global float *rtData,__global float *otData)
{
- const unsigned int id = get_global_id(0);
- otData[id] = ltData[id] / rtData[id];
+ const unsigned int id = get_global_id(0);
+ otData[id] = ltData[id] / rtData[id];
}
__kernel void oclFormulaMin(__global float *input,__global int *start,__global int *end,__global float *output)
{
- const unsigned int id = get_global_id(0);
- int i=0;
- unsigned int startFlag = start[id];
- unsigned int endFlag = end[id];
- float min = input[startFlag];
- for(i=startFlag;i<=endFlag;i++)
- {
- if(input[i]<min)
- min = input[i];
- }
- output[id] = min;
+ const unsigned int id = get_global_id(0);
+ int i=0;
+ unsigned int startFlag = start[id];
+ unsigned int endFlag = end[id];
+ float min = input[startFlag];
+ for(i=startFlag;i<=endFlag;i++)
+ {
+ if(input[i]<min)
+ min = input[i];
+ }
+ output[id] = min;
}
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list