summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--formula/inc/formula/compiler.hrc4
-rw-r--r--formula/inc/formula/tokenarray.hxx6
-rw-r--r--formula/source/core/api/token.cxx6
-rw-r--r--sc/inc/tokenarray.hxx10
-rw-r--r--sc/source/core/tool/token.cxx80
5 files changed, 104 insertions, 2 deletions
diff --git a/formula/inc/formula/compiler.hrc b/formula/inc/formula/compiler.hrc
index 8acfff652d07..053947c2a796 100644
--- a/formula/inc/formula/compiler.hrc
+++ b/formula/inc/formula/compiler.hrc
@@ -94,6 +94,8 @@
#define SC_OPCODE_NEG_SUB 62
#define SC_OPCODE_STOP_UN_OP 63
+#define SC_OPCODE_START_FUNCTION 65
+
/*** Functions without parameters ***/
#define SC_OPCODE_START_NO_PAR 65
#define SC_OPCODE_PI 65
@@ -403,6 +405,8 @@
#define SC_OPCODE_STOP_2_PAR 407
#define SC_OPCODE_LAST_OPCODE_ID 406 /* last OpCode */
+#define SC_OPCODE_STOP_FUNCTION 407
+
/*** Internal ***/
#define SC_OPCODE_INTERNAL_BEGIN 9999
#define SC_OPCODE_TTT 9999
diff --git a/formula/inc/formula/tokenarray.hxx b/formula/inc/formula/tokenarray.hxx
index 42c92127c856..875b055a621a 100644
--- a/formula/inc/formula/tokenarray.hxx
+++ b/formula/inc/formula/tokenarray.hxx
@@ -192,6 +192,12 @@ public:
*/
bool Fill(const com::sun::star::uno::Sequence< com::sun::star::sheet::FormulaToken >& _aSequence, ExternalReferenceHelper* _pRef = NULL);
+ /**
+ * Do some checking based on the individual tokens. For now, we use this
+ * only to check whether we can vectorize the token array.
+ */
+ virtual void CheckToken( const FormulaToken& t );
+
FormulaToken* AddToken( const FormulaToken& );
FormulaToken* AddString( const sal_Unicode* pStr );
FormulaToken* AddString( const String& rStr );
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 875055519ddd..84180f02fcf1 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -708,6 +708,11 @@ void FormulaTokenArray::Clear()
ClearRecalcMode();
}
+void FormulaTokenArray::CheckToken( const FormulaToken& /*r*/ )
+{
+ // Do nothing.
+}
+
FormulaToken* FormulaTokenArray::AddToken( const FormulaToken& r )
{
return Add( r.Clone() );
@@ -724,6 +729,7 @@ FormulaToken* FormulaTokenArray::Add( FormulaToken* t )
pCode = new FormulaToken*[ MAXCODE ];
if( nLen < MAXCODE-1 )
{
+ CheckToken(*t);
pCode[ nLen++ ] = t;
if( t->GetOpCode() == ocPush
&& ( t->GetType() == svSingleRef || t->GetType() == svDoubleRef ) )
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index e3b7d5679272..5c09d288b7af 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -33,9 +33,18 @@ struct ScComplexRefData;
class SC_DLLPUBLIC ScTokenArray : public formula::FormulaTokenArray
{
friend class ScCompiler;
+
+ /**
+ * When vectorization is enabled, we could potentially mass-calculate a
+ * series of formula token arrays in adjacent formula cells in one step,
+ * provided that they all contain identical set of tokens.
+ */
+ enum VectorState { Disabled = 0, Enabled, CheckReference };
+
bool ImplGetReference( ScRange& rRange, bool bValidOnly ) const;
size_t mnHashValue;
+ VectorState meVectorState;
public:
ScTokenArray();
@@ -61,6 +70,7 @@ public:
formula::FormulaToken* AddRawToken( const ScRawToken& );
virtual bool AddFormulaToken(const com::sun::star::sheet::FormulaToken& _aToken,formula::ExternalReferenceHelper* _pRef);
+ virtual void CheckToken( const formula::FormulaToken& r );
virtual formula::FormulaToken* AddOpCode( OpCode eCode );
/** ScSingleRefToken with ocPush. */
formula::FormulaToken* AddSingleReference( const ScSingleRefData& rRef );
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index b59517756202..a5eb79679b31 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -1246,6 +1246,78 @@ bool ScTokenArray::AddFormulaToken(const com::sun::star::sheet::FormulaToken& _a
}
return bError;
}
+
+void ScTokenArray::CheckToken( const FormulaToken& r )
+{
+ if (meVectorState == Disabled)
+ // It's already disabled. No more checking needed.
+ return;
+
+ OpCode eOp = r.GetOpCode();
+
+ if (SC_OPCODE_START_FUNCTION <= eOp && eOp < SC_OPCODE_STOP_FUNCTION)
+ {
+ // This is a function opcode. For now, we only support vectorization
+ // for min, max, sum and average.
+ switch (eOp)
+ {
+ case ocAverage:
+ case ocMin:
+ case ocMinA:
+ case ocMax:
+ case ocMaxA:
+ case ocSum:
+ // Don't change the state.
+ break;
+ default:
+ meVectorState = Disabled;
+ }
+ return;
+ }
+
+ if (eOp == ocPush)
+ {
+ // This is a stack variable. See if this is a reference.
+
+ switch (r.GetType())
+ {
+ case svByte:
+ case svDouble:
+ case svString:
+ // Don't change the state.
+ break;
+ case svSingleRef:
+ case svDoubleRef:
+ // Depends on the reference state.
+ meVectorState = CheckReference;
+ break;
+ case svError:
+ case svEmptyCell:
+ case svExternal:
+ case svExternalDoubleRef:
+ case svExternalName:
+ case svExternalSingleRef:
+ case svFAP:
+ case svHybridCell:
+ case svHybridValueCell:
+ case svIndex:
+ case svJump:
+ case svJumpMatrix:
+ case svMatrix:
+ case svMatrixCell:
+ case svMissing:
+ case svRefList:
+ case svSep:
+ case svSubroutine:
+ case svUnknown:
+ // We don't support vectorization on these.
+ meVectorState = Disabled;
+ default:
+ ;
+ }
+ }
+}
+
bool ScTokenArray::ImplGetReference( ScRange& rRange, bool bValidOnly ) const
{
bool bIs = false;
@@ -1380,13 +1452,15 @@ bool ScTokenArray::IsValidReference( ScRange& rRange ) const
ScTokenArray::ScTokenArray() :
FormulaTokenArray(),
- mnHashValue(0)
+ mnHashValue(0),
+ meVectorState(Enabled)
{
}
ScTokenArray::ScTokenArray( const ScTokenArray& rArr ) :
FormulaTokenArray(rArr),
- mnHashValue(rArr.mnHashValue)
+ mnHashValue(rArr.mnHashValue),
+ meVectorState(rArr.meVectorState)
{
}
@@ -1411,6 +1485,8 @@ ScTokenArray* ScTokenArray::Clone() const
p->nError = nError;
p->bHyperLink = bHyperLink;
p->mnHashValue = mnHashValue;
+ p->meVectorState = meVectorState;
+
FormulaToken** pp;
if( nLen )
{