[Libreoffice-commits] core.git: Branch 'feature/calc-group-interpreter' - 3 commits - sc/inc sc/source
Kohei Yoshida
kohei.yoshida at gmail.com
Tue Jul 2 20:01:13 PDT 2013
sc/inc/formulacell.hxx | 11 +++++++--
sc/inc/types.hxx | 7 ++++++
sc/source/core/data/column2.cxx | 20 ++++++++++++++---
sc/source/core/data/formulacell.cxx | 40 ++++++++++++++++++++++++++++-------
sc/source/core/tool/formulagroup.cxx | 10 ++++----
5 files changed, 69 insertions(+), 19 deletions(-)
New commits:
commit cd0e3f9b003aa340248d9ddf9ea58811e1d9a977
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 22:23:56 2013 -0400
Forgot to remove these debug statements.
Change-Id: I680750c43dce4b6e7f9b9ed0a6b8550bdf485a8c
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 6d99428..c3e8a951 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3130,12 +3130,8 @@ bool ScFormulaCell::InterpretFormulaGroup()
if (!xGroup || !pCode)
return false;
- fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: calc state = %d\n", xGroup->meCalcState);
if (xGroup->meCalcState == sc::GroupCalcDisabled)
- {
- fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: group calc disabled.\n");
return false;
- }
switch (pCode->GetVectorState())
{
@@ -3160,7 +3156,6 @@ bool ScFormulaCell::InterpretFormulaGroup()
GroupTokenConverter aConverter(aCxt, aCode, *pDocument, *this, aTopPos);
if (!aConverter.convert(*pCode))
{
- fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: disabling group calc due to failed conversion\n");
xGroup->meCalcState = sc::GroupCalcDisabled;
return false;
}
@@ -3168,7 +3163,6 @@ bool ScFormulaCell::InterpretFormulaGroup()
xGroup->meCalcState = sc::GroupCalcRunning;
if (!sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, aTopPos, xGroup, aCode))
{
- fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: disabling group calc due to failed calculation\n");
xGroup->meCalcState = sc::GroupCalcDisabled;
return false;
}
commit 9356c1a39171a1f85596218c003a949d0d1cecd4
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 22:10:25 2013 -0400
Detect circular dependency in formula groups to fallback to cell-based.
Change-Id: Icfb4fd4be4e0c1f6f450fb8ddce57c7b79568e6f
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 9ade34f..0f570d2 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -24,6 +24,7 @@
#include "formula/tokenarray.hxx"
#include "svl/listener.hxx"
+#include "types.hxx"
#include <set>
@@ -40,19 +41,23 @@ struct ScSimilarFormulaDelta;
struct SC_DLLPUBLIC ScFormulaCellGroup
{
- sal_Int32 mnRefCount;
+ mutable size_t mnRefCount;
+
SCROW mnStart; // Start offset of that cell
SCROW mnLength; // How many of these do we have ?
bool mbInvariant;
+ sc::GroupCalcState meCalcState;
ScFormulaCellGroup();
~ScFormulaCellGroup();
};
-inline void intrusive_ptr_add_ref(ScFormulaCellGroup *p)
+
+inline void intrusive_ptr_add_ref(const ScFormulaCellGroup *p)
{
p->mnRefCount++;
}
-inline void intrusive_ptr_release(ScFormulaCellGroup *p)
+
+inline void intrusive_ptr_release(const ScFormulaCellGroup *p)
{
if( --p->mnRefCount == 0 )
delete p;
diff --git a/sc/inc/types.hxx b/sc/inc/types.hxx
index 487afcd..3879e99 100644
--- a/sc/inc/types.hxx
+++ b/sc/inc/types.hxx
@@ -54,6 +54,13 @@ const sal_uInt16 MatrixEdgeTop = 8;
const sal_uInt16 MatrixEdgeRight = 16;
const sal_uInt16 MatrixEdgeOpen = 32;
+enum GroupCalcState
+{
+ GroupCalcEnabled,
+ GroupCalcRunning,
+ GroupCalcDisabled
+};
+
}
#endif
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index ef32f54..542cd92 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -2169,10 +2169,15 @@ bool appendDouble(
nLenRemain = 0;
}
+ sal_uInt16 nErr;
+ double fVal;
for (; itData != itDataEnd; ++itData)
{
ScFormulaCell& rFC = **itData;
- rArray.push_back(rFC.GetValue());
+ if (!rFC.GetErrorOrValue(nErr, fVal) || nErr)
+ return false;
+
+ rArray.push_back(fVal);
}
}
break;
@@ -2241,6 +2246,9 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
break;
case sc::element_type_formula:
{
+ sal_uInt16 nErr;
+ double fVal;
+
rCxt.maArrays.push_back(new sc::FormulaGroupContext::DoubleArrayType);
sc::FormulaGroupContext::DoubleArrayType& rArray = rCxt.maArrays.back();
rArray.reserve(nLenRequested);
@@ -2255,7 +2263,10 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
for (; it != itEnd; ++it)
{
ScFormulaCell& rCell = **it;
- rArray.push_back(rCell.GetValue()); // the cell may be interpreted.
+ if (!rCell.GetErrorOrValue(nErr, fVal) || nErr)
+ return NULL;
+
+ rArray.push_back(fVal);
}
return &rArray[0];
@@ -2267,7 +2278,10 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
for (; it != itEnd; ++it)
{
ScFormulaCell& rCell = **it;
- rArray.push_back(rCell.GetValue()); // the cell may be interpreted.
+ if (!rCell.GetErrorOrValue(nErr, fVal) || nErr)
+ return NULL;
+
+ rArray.push_back(fVal);
}
// Fill the remaining array with values from the following blocks.
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 523995b..6d99428 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -382,7 +382,11 @@ void adjustDBRange(ScToken* pToken, ScDocument& rNewDoc, const ScDocument* pOldD
}
ScFormulaCellGroup::ScFormulaCellGroup() :
- mnRefCount(0), mnStart(0), mnLength(0), mbInvariant(false)
+ mnRefCount(0),
+ mnStart(0),
+ mnLength(0),
+ mbInvariant(false),
+ meCalcState(sc::GroupCalcEnabled)
{
}
@@ -1559,6 +1563,9 @@ void ScFormulaCell::SetDirty( bool bDirtyFlag )
void ScFormulaCell::SetDirtyVar()
{
bDirty = true;
+ if (xGroup)
+ xGroup->meCalcState = sc::GroupCalcEnabled;
+
// mark the sheet of this cell to be calculated
//#FIXME do we need to revert this remnant of old fake vba events? pDocument->AddCalculateTable( aPos.Tab() );
}
@@ -1623,7 +1630,7 @@ void ScFormulaCell::SetErrCode( sal_uInt16 n )
void ScFormulaCell::AddRecalcMode( ScRecalcMode nBits )
{
if ( (nBits & RECALCMODE_EMASK) != RECALCMODE_NORMAL )
- bDirty = true;
+ SetDirtyVar();
if ( nBits & RECALCMODE_ONLOAD_ONCE )
{ // OnLoadOnce nur zum Dirty setzen nach Filter-Import
nBits = (nBits & ~RECALCMODE_EMASK) | RECALCMODE_NORMAL;
@@ -2974,9 +2981,10 @@ class GroupTokenConverter
ScTokenArray& mrGroupTokens;
ScDocument& mrDoc;
ScFormulaCell& mrCell;
+ const ScAddress& mrPos;
public:
- GroupTokenConverter(sc::FormulaGroupContext& rCxt, ScTokenArray& rGroupTokens, ScDocument& rDoc, ScFormulaCell& rCell) :
- mrCxt(rCxt), mrGroupTokens(rGroupTokens), mrDoc(rDoc), mrCell(rCell) {}
+ GroupTokenConverter(sc::FormulaGroupContext& rCxt, ScTokenArray& rGroupTokens, ScDocument& rDoc, ScFormulaCell& rCell, const ScAddress& rPos) :
+ mrCxt(rCxt), mrGroupTokens(rGroupTokens), mrDoc(rDoc), mrCell(rCell), mrPos(rPos) {}
bool convert(ScTokenArray& rCode)
{
@@ -2994,8 +3002,7 @@ public:
case svSingleRef:
{
ScSingleRefData aRef = pToken->GetSingleRef();
- aRef.CalcAbsIfRel(mrCell.aPos);
- ScAddress aRefPos(aRef.nCol, aRef.nRow, aRef.nTab);
+ ScAddress aRefPos = aRef.toAbs(mrPos);
if (aRef.IsRowRel())
{
// Fetch double array guarantees that the length of the
@@ -3123,6 +3130,13 @@ bool ScFormulaCell::InterpretFormulaGroup()
if (!xGroup || !pCode)
return false;
+ fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: calc state = %d\n", xGroup->meCalcState);
+ if (xGroup->meCalcState == sc::GroupCalcDisabled)
+ {
+ fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: group calc disabled.\n");
+ return false;
+ }
+
switch (pCode->GetVectorState())
{
case FormulaVectorEnabled:
@@ -3141,10 +3155,26 @@ bool ScFormulaCell::InterpretFormulaGroup()
sc::FormulaGroupContext aCxt;
ScTokenArray aCode;
- GroupTokenConverter aConverter(aCxt, aCode, *pDocument, *this);
+ ScAddress aTopPos = aPos;
+ aTopPos.SetRow(xGroup->mnStart);
+ GroupTokenConverter aConverter(aCxt, aCode, *pDocument, *this, aTopPos);
if (!aConverter.convert(*pCode))
+ {
+ fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: disabling group calc due to failed conversion\n");
+ xGroup->meCalcState = sc::GroupCalcDisabled;
+ return false;
+ }
+
+ xGroup->meCalcState = sc::GroupCalcRunning;
+ if (!sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, aTopPos, xGroup, aCode))
+ {
+ fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup: disabling group calc due to failed calculation\n");
+ xGroup->meCalcState = sc::GroupCalcDisabled;
return false;
- return sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, aPos, xGroup, aCode);
+ }
+
+ xGroup->meCalcState = sc::GroupCalcEnabled;
+ return true;
}
bool ScFormulaCell::InterpretInvariantFormulaGroup()
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index e7f2a13..b4fd646 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -35,18 +35,14 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
{
// Decompose the group into individual cells and calculate them individually.
- // Always set the top row to be the top of the group. Grouped formula
- // cells are to be calculated for its full segment at all times.
-
- ScAddress aTopPos = rTopPos;
- aTopPos.SetRow(xGroup->mnStart);
- ScAddress aTmpPos = aTopPos;
+ // The caller must ensure that the top position is the start position of
+ // the group.
+ ScAddress aTmpPos = rTopPos;
std::vector<double> aResults;
aResults.reserve(xGroup->mnLength);
- for (SCROW i = 0; i < xGroup->mnLength; ++i)
+ for (SCROW i = 0; i < xGroup->mnLength; ++i, aTmpPos.IncRow())
{
- aTmpPos.SetRow(aTopPos.Row() + i);
ScTokenArray aCode2;
for (const formula::FormulaToken* p = rCode.First(); p; p = rCode.Next())
{
@@ -105,7 +101,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
} // for loop end (xGroup->mnLength)
if (!aResults.empty())
- rDoc.SetFormulaResults(aTopPos, &aResults[0], aResults.size());
+ rDoc.SetFormulaResults(rTopPos, &aResults[0], aResults.size());
return true;
}
commit 90b6b0fbbd28dc27ebd119126af6ab84e4ca55a4
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 18:55:29 2013 -0400
Actually we need to reset the top row to be the top of the group.
To ensure that a group of formula cells are either all clean or all
dirty at any given time. We'll fallback to non-grouped calculation
mode if that's not possible.
Change-Id: I8a5d4740571ca149d32a4630555e3c213c222ef3
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index ae0b0d6..e7f2a13 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -35,14 +35,18 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
{
// Decompose the group into individual cells and calculate them individually.
- ScAddress aTmpPos = rTopPos;
- SCROW nOffset = rTopPos.Row() - xGroup->mnStart;
- SCROW nLength = xGroup->mnLength - nOffset;
+ // Always set the top row to be the top of the group. Grouped formula
+ // cells are to be calculated for its full segment at all times.
+
+ ScAddress aTopPos = rTopPos;
+ aTopPos.SetRow(xGroup->mnStart);
+ ScAddress aTmpPos = aTopPos;
+
std::vector<double> aResults;
- aResults.reserve(nLength);
- for (SCROW i = 0; i < nLength; ++i)
+ aResults.reserve(xGroup->mnLength);
+ for (SCROW i = 0; i < xGroup->mnLength; ++i)
{
- aTmpPos.SetRow(rTopPos.Row() + i);
+ aTmpPos.SetRow(aTopPos.Row() + i);
ScTokenArray aCode2;
for (const formula::FormulaToken* p = rCode.First(); p; p = rCode.Next())
{
@@ -101,7 +105,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
} // for loop end (xGroup->mnLength)
if (!aResults.empty())
- rDoc.SetFormulaResults(rTopPos, &aResults[0], aResults.size());
+ rDoc.SetFormulaResults(aTopPos, &aResults[0], aResults.size());
return true;
}
More information about the Libreoffice-commits
mailing list