[Libreoffice-commits] core.git: 4 commits - formula/source include/formula sc/inc sc/Library_sc.mk sc/source
Kohei Yoshida
kohei.yoshida at gmail.com
Thu Sep 5 22:38:24 PDT 2013
formula/source/core/api/vectortoken.cxx | 19 ++-
include/formula/vectortoken.hxx | 25 ++++-
sc/Library_sc.mk | 1
sc/inc/column.hxx | 3
sc/inc/document.hxx | 5 -
sc/inc/formulagroup.hxx | 9 +
sc/inc/table.hxx | 3
sc/inc/token.hxx | 31 ++++++
sc/inc/types.hxx | 15 +++
sc/source/core/data/column2.cxx | 72 ++++++++++----
sc/source/core/data/document.cxx | 8 +
sc/source/core/data/formulacell.cxx | 18 ++-
sc/source/core/data/table1.cxx | 10 +-
sc/source/core/data/types.cxx | 27 +++++
sc/source/core/inc/interpre.hxx | 12 ++
sc/source/core/opencl/formulagroupcl.cxx | 22 ++--
sc/source/core/tool/formulagroup.cxx | 31 ++++--
sc/source/core/tool/interpr1.cxx | 153 ++++++++++++++++---------------
sc/source/core/tool/interpr4.cxx | 100 +++++++++++++++++++-
sc/source/core/tool/interpr5.cxx | 14 ++
sc/source/core/tool/token.cxx | 48 +++++++++
21 files changed, 477 insertions(+), 149 deletions(-)
New commits:
commit 8e6b22b12322175e9aff643af45f275cb8c9cc5e
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Fri Sep 6 01:18:26 2013 -0400
Wrong place to apply implicit intersection. Do it at the very last.
Change-Id: I4b1e9d136d45f169ad1c1efee2275bab7dfe0f49
diff --git a/sc/inc/token.hxx b/sc/inc/token.hxx
index 32cdf5a..a852dd8 100644
--- a/sc/inc/token.hxx
+++ b/sc/inc/token.hxx
@@ -36,6 +36,12 @@
// Matrix token constants.
#define MATRIX_TOKEN_HAS_RANGE 1
+namespace sc {
+
+struct RangeMatrix;
+
+}
+
class ScJumpMatrix;
typedef ::std::vector< ScComplexRefData > ScRefList;
@@ -190,6 +196,7 @@ class ScMatrixRangeToken : public ScToken
ScComplexRefData maRef;
public:
ScMatrixRangeToken( const ScMatrixRef& p, const ScComplexRefData& rRef );
+ ScMatrixRangeToken( const sc::RangeMatrix& rMat );
ScMatrixRangeToken( const ScMatrixRangeToken& r );
virtual sal_uInt8 GetByte() const;
diff --git a/sc/inc/types.hxx b/sc/inc/types.hxx
index f03ccc0..045d6b1 100644
--- a/sc/inc/types.hxx
+++ b/sc/inc/types.hxx
@@ -68,8 +68,10 @@ struct RangeMatrix
ScMatrixRef mpMat;
sal_Int32 mnCol1;
sal_Int32 mnRow1;
+ sal_Int32 mnTab1;
sal_Int32 mnCol2;
sal_Int32 mnRow2;
+ sal_Int32 mnTab2;
RangeMatrix();
diff --git a/sc/source/core/data/types.cxx b/sc/source/core/data/types.cxx
index 566d088..b45a0b1 100644
--- a/sc/source/core/data/types.cxx
+++ b/sc/source/core/data/types.cxx
@@ -12,11 +12,14 @@
namespace sc {
-RangeMatrix::RangeMatrix() : mpMat(NULL), mnCol1(-1), mnRow1(-1), mnCol2(-1), mnRow2(-1) {}
+RangeMatrix::RangeMatrix() :
+ mpMat(NULL), mnCol1(-1), mnRow1(-1), mnTab1(-1), mnCol2(-1), mnRow2(-1), mnTab2(-1) {}
bool RangeMatrix::isRangeValid() const
{
- return mnCol1 >= 0 && mnRow1 >= 0 && mnCol2 >= 0 && mnRow2 >= 0 && mnCol1 <= mnCol2 && mnRow1 <= mnRow2;
+ return mnCol1 >= 0 && mnRow1 >= 0 && mnTab1 >=0 &&
+ mnCol2 >= 0 && mnRow2 >= 0 && mnTab2 >= 0 &&
+ mnCol1 <= mnCol2 && mnRow1 <= mnRow2 && mnTab1 <= mnTab2;
}
}
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index bb9f919..b615b34 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -319,6 +319,7 @@ void PushExternalSingleRef(sal_uInt16 nFileId, const String& rTabName,
void PushExternalDoubleRef(sal_uInt16 nFileId, const String& rTabName,
SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
SCCOL nCol2, SCROW nRow2, SCTAB nTab2);
+void PushMatrix( const sc::RangeMatrix& rMat );
void PushMatrix(const ScMatrixRef& pMat);
void PushError( sal_uInt16 nError );
/// Raw stack type without default replacements.
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index fb7b7dd..33eb3da 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -1195,8 +1195,10 @@ sc::RangeMatrix ScInterpreter::CompareMat( ScCompareOptions* pOptions )
aRes.mnCol1 = aMat[i].mnCol1;
aRes.mnRow1 = aMat[i].mnRow1;
+ aRes.mnTab1 = aMat[i].mnTab1;
aRes.mnCol2 = aMat[i].mnCol2;
aRes.mnRow2 = aMat[i].mnRow2;
+ aRes.mnTab2 = aMat[i].mnTab2;
for (SCSIZE j = 0; j < nC; ++j)
{
@@ -1270,29 +1272,6 @@ ScMatrixRef ScInterpreter::QueryMat( const ScMatrixRef& pMat, ScCompareOptions&
return pResultMatrix;
}
-namespace {
-
-double applyImplicitIntersection(const sc::RangeMatrix& rMat, const ScAddress& rPos)
-{
- if (rMat.mnRow1 <= rPos.Row() && rPos.Row() <= rMat.mnRow2 && rMat.mnCol1 == rMat.mnCol2)
- {
- SCROW nOffset = rPos.Row() - rMat.mnRow1;
- return rMat.mpMat->GetDouble(0, nOffset);
- }
-
- if (rMat.mnCol1 <= rPos.Col() && rPos.Col() <= rMat.mnCol2 && rMat.mnRow1 == rMat.mnRow2)
- {
- SCROW nOffset = rPos.Col() - rMat.mnCol1;
- return rMat.mpMat->GetDouble(nOffset, 0);
- }
-
- double fVal;
- rtl::math::setNan(&fVal);
- return fVal;
-}
-
-}
-
void ScInterpreter::ScEqual()
{
if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
@@ -1304,22 +1283,8 @@ void ScInterpreter::ScEqual()
return;
}
- if (aMat.isRangeValid())
- {
- // This matrix represents a range reference. Apply implicit intersection.
- double fVal = applyImplicitIntersection(aMat, aPos);
- if (rtl::math::isNan(fVal))
- {
- PushError(errCellNoValue);
- return;
- }
-
- PushInt(fVal == 0.0);
- return;
- }
-
aMat.mpMat->CompareEqual();
- PushMatrix(aMat.mpMat);
+ PushMatrix(aMat);
}
else
PushInt( Compare() == 0 );
@@ -1337,22 +1302,8 @@ void ScInterpreter::ScNotEqual()
return;
}
- if (aMat.isRangeValid())
- {
- // This matrix represents a range reference. Apply implicit intersection.
- double fVal = applyImplicitIntersection(aMat, aPos);
- if (rtl::math::isNan(fVal))
- {
- PushError(errCellNoValue);
- return;
- }
-
- PushInt(fVal != 0.0);
- return;
- }
-
aMat.mpMat->CompareNotEqual();
- PushMatrix(aMat.mpMat);
+ PushMatrix(aMat);
}
else
PushInt( Compare() != 0 );
@@ -1370,22 +1321,8 @@ void ScInterpreter::ScLess()
return;
}
- if (aMat.isRangeValid())
- {
- // This matrix represents a range reference. Apply implicit intersection.
- double fVal = applyImplicitIntersection(aMat, aPos);
- if (rtl::math::isNan(fVal))
- {
- PushError(errCellNoValue);
- return;
- }
-
- PushInt(fVal < 0.0);
- return;
- }
-
aMat.mpMat->CompareLess();
- PushMatrix(aMat.mpMat);
+ PushMatrix(aMat);
}
else
PushInt( Compare() < 0 );
@@ -1403,22 +1340,8 @@ void ScInterpreter::ScGreater()
return;
}
- if (aMat.isRangeValid())
- {
- // This matrix represents a range reference. Apply implicit intersection.
- double fVal = applyImplicitIntersection(aMat, aPos);
- if (rtl::math::isNan(fVal))
- {
- PushError(errCellNoValue);
- return;
- }
-
- PushInt(fVal > 0.0);
- return;
- }
-
aMat.mpMat->CompareGreater();
- PushMatrix(aMat.mpMat);
+ PushMatrix(aMat);
}
else
PushInt( Compare() > 0 );
@@ -1436,22 +1359,8 @@ void ScInterpreter::ScLessEqual()
return;
}
- if (aMat.isRangeValid())
- {
- // This matrix represents a range reference. Apply implicit intersection.
- double fVal = applyImplicitIntersection(aMat, aPos);
- if (rtl::math::isNan(fVal))
- {
- PushError(errCellNoValue);
- return;
- }
-
- PushInt(fVal <= 0.0);
- return;
- }
-
aMat.mpMat->CompareLessEqual();
- PushMatrix(aMat.mpMat);
+ PushMatrix(aMat);
}
else
PushInt( Compare() <= 0 );
@@ -1469,22 +1378,8 @@ void ScInterpreter::ScGreaterEqual()
return;
}
- if (aMat.isRangeValid())
- {
- // This matrix represents a range reference. Apply implicit intersection.
- double fVal = applyImplicitIntersection(aMat, aPos);
- if (rtl::math::isNan(fVal))
- {
- PushError(errCellNoValue);
- return;
- }
-
- PushInt(fVal >= 0.0);
- return;
- }
-
aMat.mpMat->CompareGreaterEqual();
- PushMatrix(aMat.mpMat);
+ PushMatrix(aMat);
}
else
PushInt( Compare() >= 0 );
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 7beb580..7288613 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -1817,8 +1817,10 @@ sc::RangeMatrix ScInterpreter::PopRangeMatrix()
{
aRet.mnCol1 = rRef.Ref1.Col();
aRet.mnRow1 = rRef.Ref1.Row();
+ aRet.mnTab1 = rRef.Ref1.Tab();
aRet.mnCol2 = rRef.Ref2.Col();
aRet.mnRow2 = rRef.Ref2.Row();
+ aRet.mnTab2 = rRef.Ref2.Tab();
}
}
}
@@ -1953,6 +1955,19 @@ void ScInterpreter::PushExternalDoubleRef(
}
}
+void ScInterpreter::PushMatrix( const sc::RangeMatrix& rMat )
+{
+ if (!rMat.isRangeValid())
+ {
+ // Just push the matrix part only.
+ PushMatrix(rMat.mpMat);
+ return;
+ }
+
+ rMat.mpMat->SetErrorInterpreter(NULL);
+ nGlobalError = 0;
+ PushTempTokenWithoutError(new ScMatrixRangeToken(rMat));
+}
void ScInterpreter::PushMatrix(const ScMatrixRef& pMat)
{
@@ -3735,6 +3750,28 @@ void ScInterpreter::GlobalExit()
DELETEZ(pGlobalStack);
}
+namespace {
+
+double applyImplicitIntersection(const sc::RangeMatrix& rMat, const ScAddress& rPos)
+{
+ if (rMat.mnRow1 <= rPos.Row() && rPos.Row() <= rMat.mnRow2 && rMat.mnCol1 == rMat.mnCol2)
+ {
+ SCROW nOffset = rPos.Row() - rMat.mnRow1;
+ return rMat.mpMat->GetDouble(0, nOffset);
+ }
+
+ if (rMat.mnCol1 <= rPos.Col() && rPos.Col() <= rMat.mnCol2 && rMat.mnRow1 == rMat.mnRow2)
+ {
+ SCROW nOffset = rPos.Col() - rMat.mnCol1;
+ return rMat.mpMat->GetDouble(nOffset, 0);
+ }
+
+ double fVal;
+ rtl::math::setNan(&fVal);
+ return fVal;
+}
+
+}
StackVar ScInterpreter::Interpret()
{
@@ -4315,17 +4352,29 @@ StackVar ScInterpreter::Interpret()
}
break;
case svExternalDoubleRef:
- case svMatrix :
{
ScMatrixRef xMat;
- if (pCur->GetType() == svMatrix)
- xMat = PopMatrix();
- else
- PopExternalDoubleRef(xMat);
-
+ PopExternalDoubleRef(xMat);
QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
}
break;
+ case svMatrix :
+ {
+ sc::RangeMatrix aMat = PopRangeMatrix();
+ if (aMat.isRangeValid())
+ {
+ // This matrix represents a range reference. Apply implicit intersection.
+ double fVal = applyImplicitIntersection(aMat, aPos);
+ if (rtl::math::isNan(fVal))
+ PushError(errCellNoValue);
+ else
+ PushInt(fVal);
+ }
+ else
+ // This is a normal matrix.
+ QueryMatrixType(aMat.mpMat, nRetTypeExpr, nRetIndexExpr);
+ }
+ break;
case svExternalSingleRef:
{
ScExternalRefCache::TokenRef pToken;
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 9f5a7e6..08455f5 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -38,6 +38,7 @@
#include "externalrefmgr.hxx"
#include "document.hxx"
#include "refupdatecontext.hxx"
+#include "types.hxx"
using ::std::vector;
@@ -807,6 +808,12 @@ bool ScMatrixToken::operator==( const FormulaToken& r ) const
ScMatrixRangeToken::ScMatrixRangeToken( const ScMatrixRef& p, const ScComplexRefData& rRef ) :
ScToken(formula::svMatrix), mpMatrix(p), maRef(rRef) {}
+ScMatrixRangeToken::ScMatrixRangeToken( const sc::RangeMatrix& rMat ) :
+ ScToken(formula::svMatrix), mpMatrix(rMat.mpMat)
+{
+ maRef.InitRange(rMat.mnCol1, rMat.mnRow1, rMat.mnTab1, rMat.mnCol2, rMat.mnRow2, rMat.mnTab2);
+}
+
ScMatrixRangeToken::ScMatrixRangeToken( const ScMatrixRangeToken& r ) :
ScToken(r), mpMatrix(r.mpMatrix), maRef(r.maRef) {}
commit 7969bb659ef78ec6e1aaaf922757419795a823de
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Thu Sep 5 20:29:18 2013 -0400
Handle string or edit cells when resolving static reference for group calc.
Change-Id: Ifb2d0d6e7c9f3040bca61b5bdce14d853058d954
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 658a316..9d0130c 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1823,6 +1823,17 @@ formula::FormulaTokenRef ScColumn::ResolveStaticReference( SCROW nRow )
return formula::FormulaTokenRef(new formula::FormulaStringToken(p->GetString()));
}
+ case sc::element_type_string:
+ {
+ OUString aStr = sc::string_block::at(*it->data, aPos.second);
+ return formula::FormulaTokenRef(new formula::FormulaStringToken(aStr));
+ }
+ case sc::element_type_edittext:
+ {
+ const EditTextObject* pText = sc::edittext_block::at(*it->data, aPos.second);
+ OUString aStr = ScEditUtil::GetString(*pText, pDocument);
+ return formula::FormulaTokenRef(new formula::FormulaStringToken(aStr));
+ }
case sc::element_type_empty:
default:
// Return a value of 0.0 in all the other cases.
commit e462eb1183c0e52c06786296b39c121ea3671199
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Wed Sep 4 18:33:41 2013 -0400
Allow storage of string arrays in vector ref tokens.
Change-Id: Id2bc5a0343afeae387d896a9c369586a13081cd5
diff --git a/formula/source/core/api/vectortoken.cxx b/formula/source/core/api/vectortoken.cxx
index 74339397..557e0c0 100644
--- a/formula/source/core/api/vectortoken.cxx
+++ b/formula/source/core/api/vectortoken.cxx
@@ -11,17 +11,24 @@
namespace formula {
+VectorRefArray::VectorRefArray() : mpNumericArray(NULL), mbNumeric(true) {}
+VectorRefArray::VectorRefArray( const double* pArray ) : mpNumericArray(pArray), mbNumeric(true) {}
+VectorRefArray::VectorRefArray( const OUString* pArray ) : mpStringArray(pArray), mbNumeric(false) {}
+
SingleVectorRefToken::SingleVectorRefToken( const double* pArray, size_t nLength ) :
- FormulaToken(svSingleVectorRef, ocPush), mpArray(pArray), mnArrayLength(nLength) {}
+ FormulaToken(svSingleVectorRef, ocPush), maArray(pArray), mnArrayLength(nLength) {}
+
+SingleVectorRefToken::SingleVectorRefToken( const VectorRefArray& rArray, size_t nLength ) :
+ FormulaToken(svSingleVectorRef, ocPush), maArray(rArray), mnArrayLength(nLength) {}
FormulaToken* SingleVectorRefToken::Clone() const
{
- return new SingleVectorRefToken(mpArray, mnArrayLength);
+ return new SingleVectorRefToken(maArray, mnArrayLength);
}
-const double* SingleVectorRefToken::GetArray() const
+const VectorRefArray& SingleVectorRefToken::GetArray() const
{
- return mpArray;
+ return maArray;
}
size_t SingleVectorRefToken::GetArrayLength() const
@@ -30,7 +37,7 @@ size_t SingleVectorRefToken::GetArrayLength() const
}
DoubleVectorRefToken::DoubleVectorRefToken(
- const std::vector<const double*>& rArrays, size_t nArrayLength, size_t nRefRowSize, bool bStartFixed, bool bEndFixed ) :
+ const std::vector<VectorRefArray>& rArrays, size_t nArrayLength, size_t nRefRowSize, bool bStartFixed, bool bEndFixed ) :
FormulaToken(svDoubleVectorRef, ocPush),
maArrays(rArrays), mnArrayLength(nArrayLength), mnRefRowSize(nRefRowSize), mbStartFixed(bStartFixed), mbEndFixed(bEndFixed) {}
@@ -39,7 +46,7 @@ FormulaToken* DoubleVectorRefToken::Clone() const
return new DoubleVectorRefToken(maArrays, mnArrayLength, mnRefRowSize, mbStartFixed, mbEndFixed);
}
-const std::vector<const double*>& DoubleVectorRefToken::GetArrays() const
+const std::vector<VectorRefArray>& DoubleVectorRefToken::GetArrays() const
{
return maArrays;
}
diff --git a/include/formula/vectortoken.hxx b/include/formula/vectortoken.hxx
index d3d0511..5186ca5 100644
--- a/include/formula/vectortoken.hxx
+++ b/include/formula/vectortoken.hxx
@@ -14,21 +14,36 @@
namespace formula {
+struct FORMULA_DLLPUBLIC VectorRefArray
+{
+ union {
+ const double* mpNumericArray;
+ const OUString* mpStringArray;
+ };
+
+ bool mbNumeric;
+
+ VectorRefArray();
+ VectorRefArray( const double* pArray );
+ VectorRefArray( const OUString* pArray );
+};
+
/**
* This token represents a single cell reference in a vectorized formula
* calculation context.
*/
class FORMULA_DLLPUBLIC SingleVectorRefToken : public FormulaToken
{
- const double* mpArray;
+ VectorRefArray maArray;
size_t mnArrayLength;
public:
SingleVectorRefToken( const double* pArray, size_t nLength );
+ SingleVectorRefToken( const VectorRefArray& rArray, size_t nLength );
virtual FormulaToken* Clone() const;
- const double* GetArray() const;
+ const VectorRefArray& GetArray() const;
size_t GetArrayLength() const;
};
@@ -38,7 +53,7 @@ public:
*/
class FORMULA_DLLPUBLIC DoubleVectorRefToken : public FormulaToken
{
- std::vector<const double*> maArrays;
+ std::vector<VectorRefArray> maArrays;
size_t mnArrayLength; /// length of all arrays.
size_t mnRefRowSize; /// original reference row size. The row size may
@@ -50,11 +65,11 @@ class FORMULA_DLLPUBLIC DoubleVectorRefToken : public FormulaToken
public:
DoubleVectorRefToken(
- const std::vector<const double*>& rArrays, size_t nArrayLength, size_t nRefRowSize, bool bStartFixed, bool bEndFixed );
+ const std::vector<VectorRefArray>& rArrays, size_t nArrayLength, size_t nRefRowSize, bool bStartFixed, bool bEndFixed );
virtual FormulaToken* Clone() const;
- const std::vector<const double*>& GetArrays() const;
+ const std::vector<VectorRefArray>& GetArrays() const;
size_t GetArrayLength() const;
size_t GetRefRowSize() const;
bool IsStartFixed() const;
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 7308d22..ba79c23 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -35,6 +35,7 @@
#include <mdds/flat_segment_tree.hpp>
namespace editeng { class SvxBorderLine; }
+namespace formula { struct VectorRefArray; }
namespace sc {
struct FormulaGroupContext;
@@ -469,7 +470,7 @@ public:
formula::FormulaTokenRef ResolveStaticReference( SCROW nRow );
bool ResolveStaticReference( ScMatrix& rMat, SCCOL nMatCol, SCROW nRow1, SCROW nRow2 );
void FillMatrix( ScMatrix& rMat, size_t nMatCol, SCROW nRow1, SCROW nRow2 ) const;
- const double* FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW nRow1, SCROW nRow2 );
+ formula::VectorRefArray FetchVectorRefArray( sc::FormulaGroupContext& rCxt, SCROW nRow1, SCROW nRow2 );
void SetFormulaResults( SCROW nRow, const double* pResults, size_t nLen );
void SetNumberFormat( SCROW nRow, sal_uInt32 nNumberFormat );
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index b91e8d3..6949b6d 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -49,6 +49,8 @@
#include "markdata.hxx"
namespace editeng { class SvxBorderLine; }
+namespace formula { struct VectorRefArray; }
+
namespace sc {
struct FormulaGroupContext;
class StartListeningContext;
@@ -59,6 +61,7 @@ namespace sc {
struct RefUpdateContext;
class EditTextIterator;
}
+
class SvxFontItem;
class KeyEvent;
@@ -1983,7 +1986,7 @@ public:
formula::FormulaTokenRef ResolveStaticReference( const ScAddress& rPos );
formula::FormulaTokenRef ResolveStaticReference( const ScRange& rRange );
- const double* FetchDoubleArray(
+ formula::VectorRefArray FetchVectorRefArray(
sc::FormulaGroupContext& rCxt, const ScAddress& rPos, SCROW nLength );
SvtBroadcaster* GetBroadcaster( const ScAddress& rPos );
diff --git a/sc/inc/formulagroup.hxx b/sc/inc/formulagroup.hxx
index 9963fc9..776b24d 100644
--- a/sc/inc/formulagroup.hxx
+++ b/sc/inc/formulagroup.hxx
@@ -23,10 +23,13 @@ namespace sc {
struct FormulaGroupContext : boost::noncopyable
{
- typedef std::vector<double> DoubleArrayType;
- typedef boost::ptr_vector<DoubleArrayType> ArrayStoreType;
+ typedef std::vector<double> NumArrayType;
+ typedef std::vector<OUString> StrArrayType;
+ typedef boost::ptr_vector<NumArrayType> NumArrayStoreType;
+ typedef boost::ptr_vector<StrArrayType> StrArrayStoreType;
- ArrayStoreType maArrays;
+ NumArrayStoreType maNumArrays;
+ StrArrayStoreType maStrArrays;
};
/**
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 69d2520..8816642 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -49,6 +49,7 @@ namespace com { namespace sun { namespace star {
}
} } }
+namespace formula { struct VectorRefArray; }
namespace sc {
struct FormulaGroupContext;
class StartListeningContext;
@@ -850,7 +851,7 @@ public:
ScFormulaVectorState GetFormulaVectorState( SCCOL nCol, SCROW nRow ) const;
formula::FormulaTokenRef ResolveStaticReference( SCCOL nCol, SCROW nRow );
formula::FormulaTokenRef ResolveStaticReference( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
- const double* FetchDoubleArray(
+ formula::VectorRefArray FetchVectorRefArray(
sc::FormulaGroupContext& rCxt, SCCOL nCol, SCROW nRow1, SCROW nRow2 );
ScRefCellValue GetRefCellValue( SCCOL nCol, SCROW nRow );
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 855be2e..658a316 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -63,6 +63,7 @@
#include <svl/listeneriter.hxx>
#include <vcl/outdev.hxx>
#include "formula/errorcodes.hxx"
+#include "formula/vectortoken.hxx"
#include <boost/scoped_ptr.hpp>
@@ -2039,7 +2040,7 @@ void ScColumn::FillMatrix( ScMatrix& rMat, size_t nMatCol, SCROW nRow1, SCROW nR
namespace {
bool appendDouble(
- sc::FormulaGroupContext::DoubleArrayType& rArray, size_t nLen,
+ sc::FormulaGroupContext::NumArrayType& rArray, size_t nLen,
sc::CellStoreType::iterator it, const sc::CellStoreType::iterator& itEnd )
{
size_t nLenRemain = nLen;
@@ -2135,10 +2136,10 @@ bool appendDouble(
}
-const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW nRow1, SCROW nRow2 )
+formula::VectorRefArray ScColumn::FetchVectorRefArray( sc::FormulaGroupContext& rCxt, SCROW nRow1, SCROW nRow2 )
{
if (nRow1 > nRow2)
- return NULL;
+ return formula::VectorRefArray();
size_t nLenRequested = nRow2 - nRow1 + 1;
sc::CellStoreType::position_type aPos = maCells.position(nRow1);
@@ -2149,23 +2150,26 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
{
// This is a numeric cell block.
if (nLenRequested <= nLen)
+ {
// Requested length fits a single block.
- return &sc::numeric_block::at(*aPos.first->data, aPos.second);
+ const double* p = &sc::numeric_block::at(*aPos.first->data, aPos.second);
+ return formula::VectorRefArray(p);
+ }
// Allocate a new array and copy the values to it.
sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aPos.first->data);
sc::numeric_block::const_iterator itEnd = sc::numeric_block::end(*aPos.first->data);
std::advance(it, aPos.second);
- rCxt.maArrays.push_back(new sc::FormulaGroupContext::DoubleArrayType(it, itEnd));
- sc::FormulaGroupContext::DoubleArrayType& rArray = rCxt.maArrays.back();
+ rCxt.maNumArrays.push_back(new sc::FormulaGroupContext::NumArrayType(it, itEnd));
+ sc::FormulaGroupContext::NumArrayType& rArray = rCxt.maNumArrays.back();
rArray.reserve(nLenRequested);
// Fill the remaining array with values from the following blocks.
++aPos.first;
if (!appendDouble(rArray, nLenRequested - nLen, aPos.first, maCells.end()))
- return NULL;
+ return formula::VectorRefArray();
- return &rArray[0];
+ return formula::VectorRefArray(&rArray[0]);
}
break;
case sc::element_type_formula:
@@ -2173,8 +2177,8 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
sal_uInt16 nErr;
double fVal;
- rCxt.maArrays.push_back(new sc::FormulaGroupContext::DoubleArrayType);
- sc::FormulaGroupContext::DoubleArrayType& rArray = rCxt.maArrays.back();
+ rCxt.maNumArrays.push_back(new sc::FormulaGroupContext::NumArrayType);
+ sc::FormulaGroupContext::NumArrayType& rArray = rCxt.maNumArrays.back();
rArray.reserve(nLenRequested);
sc::formula_block::const_iterator it = sc::formula_block::begin(*aPos.first->data);
@@ -2196,13 +2200,13 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
rCell.SetErrCode(0);
rCell.SetDirtyVar();
}
- return NULL;
+ return formula::VectorRefArray();
}
rArray.push_back(fVal);
}
- return &rArray[0];
+ return formula::VectorRefArray(&rArray[0]);
}
// Requested length goes beyond a single block. Fill the array
@@ -2219,7 +2223,7 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
rCell.SetErrCode(0);
rCell.SetDirtyVar();
}
- return NULL;
+ return formula::VectorRefArray();
}
rArray.push_back(fVal);
@@ -2228,9 +2232,22 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
// Fill the remaining array with values from the following blocks.
++aPos.first;
if (!appendDouble(rArray, nLenRequested - nLen, aPos.first, maCells.end()))
- return NULL;
+ return formula::VectorRefArray();
+
+ return formula::VectorRefArray(&rArray[0]);
+ }
+ break;
+ case sc::element_type_string:
+ {
+ if (nLenRequested <= nLen)
+ {
+ // Requested length fits a single block.
+ const OUString* p = &sc::string_block::at(*aPos.first->data, aPos.second);
+ return formula::VectorRefArray(p);
+ }
- return &rArray[0];
+ // TODO: handle cases where the requested length goes beyond the
+ // current block just like we do with numeric array.
}
break;
case sc::element_type_empty:
@@ -2238,27 +2255,27 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
if (nLenRequested <= nLen)
{
// Fill the whole length with zero.
- rCxt.maArrays.push_back(new sc::FormulaGroupContext::DoubleArrayType(nLenRequested, 0.0));
- return &rCxt.maArrays.back()[0];
+ rCxt.maNumArrays.push_back(new sc::FormulaGroupContext::NumArrayType(nLenRequested, 0.0));
+ return formula::VectorRefArray(&rCxt.maNumArrays.back()[0]);
}
// Fill the array with zero for the length of the empty block.
- rCxt.maArrays.push_back(new sc::FormulaGroupContext::DoubleArrayType(nLen, 0.0));
- sc::FormulaGroupContext::DoubleArrayType& rArray = rCxt.maArrays.back();
+ rCxt.maNumArrays.push_back(new sc::FormulaGroupContext::NumArrayType(nLen, 0.0));
+ sc::FormulaGroupContext::NumArrayType& rArray = rCxt.maNumArrays.back();
rArray.reserve(nLenRequested);
// Fill the remaining array with values from the following blocks.
++aPos.first;
if (!appendDouble(rArray, nLenRequested - nLen, aPos.first, maCells.end()))
- return NULL;
+ return formula::VectorRefArray();
- return &rArray[0];
+ return formula::VectorRefArray(&rArray[0]);
}
default:
;
}
- return NULL;
+ return formula::VectorRefArray();
}
void ScColumn::SetFormulaResults( SCROW nRow, const double* pResults, size_t nLen )
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index f316581..c6d3c79 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -95,6 +95,8 @@
#include "scopetools.hxx"
#include "refupdatecontext.hxx"
+#include "formula/vectortoken.hxx"
+
#include <map>
#include <limits>
#include <boost/scoped_ptr.hpp>
@@ -1662,14 +1664,14 @@ formula::FormulaTokenRef ScDocument::ResolveStaticReference( const ScRange& rRan
rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
}
-const double* ScDocument::FetchDoubleArray(
+formula::VectorRefArray ScDocument::FetchVectorRefArray(
sc::FormulaGroupContext& rCxt, const ScAddress& rPos, SCROW nLength )
{
SCTAB nTab = rPos.Tab();
if (!TableExists(nTab))
- return NULL;
+ return formula::VectorRefArray();
- return maTabs[nTab]->FetchDoubleArray(rCxt, rPos.Col(), rPos.Row(), rPos.Row()+nLength-1);
+ return maTabs[nTab]->FetchVectorRefArray(rCxt, rPos.Col(), rPos.Row(), rPos.Row()+nLength-1);
}
bool ScDocument::CanFitBlock( const ScRange& rOld, const ScRange& rNew )
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 4f0b90e..143351e8 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3387,11 +3387,11 @@ public:
// returned array equals or greater than the requested
// length.
- const double* pArray = mrDoc.FetchDoubleArray(mrCxt, aRefPos, nLen);
- if (!pArray)
+ formula::VectorRefArray aArray = mrDoc.FetchVectorRefArray(mrCxt, aRefPos, nLen);
+ if (!aArray.mpNumericArray)
return false;
- formula::SingleVectorRefToken aTok(pArray, nLen);
+ formula::SingleVectorRefToken aTok(aArray, nLen);
mrGroupTokens.AddToken(aTok);
}
else
@@ -3435,7 +3435,7 @@ public:
bool bAbsLast = !aRef.Ref2.IsRowRel();
ScAddress aRefPos = aAbs.aStart;
size_t nCols = aAbs.aEnd.Col() - aAbs.aStart.Col() + 1;
- std::vector<const double*> aArrays;
+ std::vector<formula::VectorRefArray> aArrays;
aArrays.reserve(nCols);
SCROW nArrayLength = nLen;
SCROW nRefRowSize = aAbs.aEnd.Row() - aAbs.aStart.Row() + 1;
@@ -3448,11 +3448,11 @@ public:
for (SCCOL i = aAbs.aStart.Col(); i <= aAbs.aEnd.Col(); ++i)
{
aRefPos.SetCol(i);
- const double* pArray = mrDoc.FetchDoubleArray(mrCxt, aRefPos, nArrayLength);
- if (!pArray)
+ formula::VectorRefArray aArray = mrDoc.FetchVectorRefArray(mrCxt, aRefPos, nArrayLength);
+ if (!aArray.mpNumericArray)
return false;
- aArrays.push_back(pArray);
+ aArrays.push_back(aArray);
}
formula::DoubleVectorRefToken aTok(aArrays, nArrayLength, nRefRowSize, bAbsFirst, bAbsLast);
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index 5f409ba..6391eee 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -49,6 +49,8 @@
#include "scmatrix.hxx"
#include "refupdatecontext.hxx"
+#include "formula/vectortoken.hxx"
+
#include <vector>
using ::std::vector;
@@ -2148,16 +2150,16 @@ formula::FormulaTokenRef ScTable::ResolveStaticReference( SCCOL nCol1, SCROW nRo
return formula::FormulaTokenRef(new ScMatrixToken(pMat));
}
-const double* ScTable::FetchDoubleArray(
+formula::VectorRefArray ScTable::FetchVectorRefArray(
sc::FormulaGroupContext& rCxt, SCCOL nCol, SCROW nRow1, SCROW nRow2 )
{
if (nRow2 < nRow1)
- return NULL;
+ return formula::VectorRefArray();
if (!ValidCol(nCol) || !ValidRow(nRow1) || !ValidRow(nRow2))
- return NULL;
+ return formula::VectorRefArray();
- return aCol[nCol].FetchDoubleArray(rCxt, nRow1, nRow2);
+ return aCol[nCol].FetchVectorRefArray(rCxt, nRow1, nRow2);
}
ScRefCellValue ScTable::GetRefCellValue( SCCOL nCol, SCROW nRow )
diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx
index c082391..0ae58e8 100644
--- a/sc/source/core/opencl/formulagroupcl.cxx
+++ b/sc/source/core/opencl/formulagroupcl.cxx
@@ -785,7 +785,7 @@ bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc, const ScAddress
else if( ocPush == p->GetOpCode() && formula::svDoubleVectorRef == p->GetType())
{
const formula::DoubleVectorRefToken* pDvr = static_cast< const formula::DoubleVectorRefToken* >( p );
- const std::vector< const double* >& rArrays = pDvr->GetArrays();
+ const std::vector<formula::VectorRefArray>& rArrays = pDvr->GetArrays();
uint rArraysSize = rArrays.size();
int nMoreColSize = 0;
DoubleVectorFormula *SvDoubleTemp = new DoubleVectorFormula();
@@ -794,7 +794,7 @@ bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc, const ScAddress
double *dpMoreColData = NULL;
for ( uint loop=0; loop < rArraysSize; loop++ )
{
- dpOclSrcData = rArrays[loop];
+ dpOclSrcData = rArrays[loop].mpNumericArray;
nSrcDataSize = pDvr->GetArrayLength();
nMoreColSize += nSrcDataSize;
dpMoreColData = (double *) realloc(dpMoreColData,nMoreColSize * sizeof(double));
@@ -808,7 +808,7 @@ bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc, const ScAddress
}
else
{
- dpOclSrcData = rArrays[0];
+ dpOclSrcData = rArrays[0].mpNumericArray;
nSrcDataSize = pDvr->GetArrayLength();
SvDoubleTemp->mdpInputData = dpOclSrcData;
SvDoubleTemp->mnInputDataSize = nSrcDataSize;
@@ -823,7 +823,7 @@ bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc, const ScAddress
else if( ocPush == p->GetOpCode() && formula::svSingleVectorRef == p->GetType() )
{
const formula::SingleVectorRefToken* pSvr = static_cast<const formula::SingleVectorRefToken*>( p );
- dpBinaryData = pSvr->GetArray();
+ dpBinaryData = pSvr->GetArray().mpNumericArray;
uint nArrayLen = pSvr->GetArrayLength();
SingleVectorFormula *SignleTemp = new SingleVectorFormula() ;
if(isSingle)
@@ -877,7 +877,7 @@ bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc, const ScAddress
else if( ocPush == p->GetOpCode() && formula::svDoubleVectorRef == p->GetType())
{
const formula::DoubleVectorRefToken* pDvr = static_cast< const formula::DoubleVectorRefToken* >( p );
- const std::vector< const double* >& rArrays = pDvr->GetArrays();
+ const std::vector<formula::VectorRefArray>& rArrays = pDvr->GetArrays();
unsigned int rArraysSize = rArrays.size();
int nMoreColSize = 0;
if(rArraysSize > 1)
@@ -885,7 +885,7 @@ bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc, const ScAddress
double *dpMoreColData = NULL;
for( uint loop=0; loop < rArraysSize; loop++ )
{
- dpOclSrcData = rArrays[loop];
+ dpOclSrcData = rArrays[loop].mpNumericArray;
nSrcDataSize = pDvr->GetArrayLength();
nMoreColSize += nSrcDataSize;
dpMoreColData = (double *) realloc(dpMoreColData,nMoreColSize * sizeof(double));
@@ -900,7 +900,7 @@ bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc, const ScAddress
}
else
{
- dpOclSrcData = rArrays[0];
+ dpOclSrcData = rArrays[0].mpNumericArray;
nSrcDataSize = pDvr->GetArrayLength();
}
srdDataPush( new SourceData( dpOclSrcData,nSrcDataSize,rArraysSize ) );
@@ -908,7 +908,7 @@ bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc, const ScAddress
else if( ocPush == p->GetOpCode() && formula::svSingleVectorRef == p->GetType() )
{
const formula::SingleVectorRefToken* pSvr = static_cast<const formula::SingleVectorRefToken*>( p );
- dpBinaryData = pSvr->GetArray();
+ dpBinaryData = pSvr->GetArray().mpNumericArray;
nSrcDataSize = pSvr->GetArrayLength();
srdDataPush( new SourceData( dpBinaryData, nSrcDataSize ) );
}
@@ -997,11 +997,11 @@ bool FormulaGroupInterpreterGroundwater::interpretCL(ScDocument& rDoc, const ScA
RETURN_IF_FAIL(p != NULL && p->GetOpCode() == ocPush && p->GetType() == formula::svDoubleVectorRef, "double vector ref expected");
// Get the range reference vector.
const formula::DoubleVectorRefToken* pDvr = static_cast<const formula::DoubleVectorRefToken*>(p);
- const std::vector<const double*>& rArrays = pDvr->GetArrays();
+ const std::vector<formula::VectorRefArray>& 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];
+ pGroundWaterDataArray = rArrays[0].mpNumericArray;
// Function:
p = rCode.NextRPN();
@@ -1015,7 +1015,7 @@ bool FormulaGroupInterpreterGroundwater::interpretCL(ScDocument& rDoc, const ScA
// Get the single reference vector.
const formula::SingleVectorRefToken* pSvr = static_cast<const formula::SingleVectorRefToken*>(p);
- pArrayToSubtractOneElementFrom = pSvr->GetArray();
+ pArrayToSubtractOneElementFrom = pSvr->GetArray().mpNumericArray;
RETURN_IF_FAIL(pSvr->GetArrayLength() == (size_t)xGroup->mnLength, "wrong single ref length");
p = rCode.NextRPN();
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index 40f4bef..2ea09c4 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -68,14 +68,17 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
case formula::svSingleVectorRef:
{
const formula::SingleVectorRefToken* p2 = static_cast<const formula::SingleVectorRefToken*>(p);
- const double* pArray = p2->GetArray();
- aCode2.AddDouble(static_cast<size_t>(i) < p2->GetArrayLength() ? pArray[i] : 0.0);
+ const formula::VectorRefArray& rArray = p2->GetArray();
+ if (rArray.mbNumeric)
+ aCode2.AddDouble(static_cast<size_t>(i) < p2->GetArrayLength() ? rArray.mpNumericArray[i] : 0.0);
+ else
+ aCode2.AddString(static_cast<size_t>(i) < p2->GetArrayLength() ? rArray.mpStringArray[i] : OUString());
}
break;
case formula::svDoubleVectorRef:
{
const formula::DoubleVectorRefToken* p2 = static_cast<const formula::DoubleVectorRefToken*>(p);
- const std::vector<const double*>& rArrays = p2->GetArrays();
+ const std::vector<formula::VectorRefArray>& rArrays = p2->GetArrays();
size_t nColSize = rArrays.size();
size_t nRowStart = p2->IsStartFixed() ? 0 : i;
size_t nRowEnd = p2->GetRefRowSize() - 1;
@@ -85,9 +88,19 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
ScMatrixRef pMat(new ScMatrix(nColSize, nRowSize, 0.0));
for (size_t nCol = 0; nCol < nColSize; ++nCol)
{
- const double* pArray = rArrays[nCol];
- pArray += nRowStart;
- pMat->PutDouble(pArray, nRowSize, nCol, 0);
+ const formula::VectorRefArray& rArray = rArrays[nCol];
+ if (rArray.mbNumeric)
+ {
+ const double* pNums = rArray.mpNumericArray;
+ pNums += nRowStart;
+ pMat->PutDouble(pNums, nRowSize, nCol, 0);
+ }
+ else
+ {
+ const OUString* pStrs = rArray.mpStringArray;
+ pStrs += nRowStart;
+ pMat->PutString(pStrs, nRowSize, nCol, 0);
+ }
}
if (p2->IsStartFixed() && p2->IsEndFixed())
commit 69047ec117cd2e0885efec1824e9c00555da4800
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Wed Sep 4 15:14:47 2013 -0400
Correctly handle implicit intersection in group interpretation.
Change-Id: I2ea6f41ad4036a6f3f5d99097e83fd988aacd105
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 3c06eaf..bd1a9a3 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -181,6 +181,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/data/table5 \
sc/source/core/data/table6 \
sc/source/core/data/tabprotection \
+ sc/source/core/data/types \
sc/source/core/data/userdat \
sc/source/core/data/validat \
sc/source/core/tool/addincfg \
diff --git a/sc/inc/token.hxx b/sc/inc/token.hxx
index 9603a87..32cdf5a 100644
--- a/sc/inc/token.hxx
+++ b/sc/inc/token.hxx
@@ -33,6 +33,9 @@
#include "scmatrix.hxx"
#include "calcmacros.hxx"
+// Matrix token constants.
+#define MATRIX_TOKEN_HAS_RANGE 1
+
class ScJumpMatrix;
typedef ::std::vector< ScComplexRefData > ScRefList;
@@ -176,6 +179,27 @@ public:
virtual FormulaToken* Clone() const { return new ScMatrixToken(*this); }
};
+/**
+ * Token storing matrix that represents values in sheet range. It stores
+ * both the values in matrix form, and the range address the matrix
+ * represents.
+ */
+class ScMatrixRangeToken : public ScToken
+{
+ ScMatrixRef mpMatrix;
+ ScComplexRefData maRef;
+public:
+ ScMatrixRangeToken( const ScMatrixRef& p, const ScComplexRefData& rRef );
+ ScMatrixRangeToken( const ScMatrixRangeToken& r );
+
+ virtual sal_uInt8 GetByte() const;
+ virtual const ScMatrix* GetMatrix() const;
+ virtual ScMatrix* GetMatrix();
+ virtual const ScComplexRefData& GetDoubleRef() const;
+ virtual ScComplexRefData& GetDoubleRef();
+ virtual bool operator==( const formula::FormulaToken& rToken ) const;
+ virtual FormulaToken* Clone() const;
+};
class ScExternalSingleRefToken : public ScToken
{
diff --git a/sc/inc/types.hxx b/sc/inc/types.hxx
index 5c11da5..f03ccc0 100644
--- a/sc/inc/types.hxx
+++ b/sc/inc/types.hxx
@@ -63,6 +63,19 @@ enum GroupCalcState
GroupCalcDisabled
};
+struct RangeMatrix
+{
+ ScMatrixRef mpMat;
+ sal_Int32 mnCol1;
+ sal_Int32 mnRow1;
+ sal_Int32 mnCol2;
+ sal_Int32 mnRow2;
+
+ RangeMatrix();
+
+ bool isRangeValid() const;
+};
+
}
#endif
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index da2f75b..4f0b90e 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3520,7 +3520,9 @@ bool ScFormulaCell::InterpretFormulaGroup()
return false;
}
- if (mxGroup->mbInvariant)
+ // TODO : Disable invariant formula group interpretation for now in order
+ // to get implicit intersection to work.
+ if (mxGroup->mbInvariant && false)
return InterpretInvariantFormulaGroup();
sc::FormulaGroupContext aCxt;
diff --git a/sc/source/core/data/types.cxx b/sc/source/core/data/types.cxx
new file mode 100644
index 0000000..566d088
--- /dev/null
+++ b/sc/source/core/data/types.cxx
@@ -0,0 +1,24 @@
+/* -*- 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 "types.hxx"
+#include "scmatrix.hxx"
+
+namespace sc {
+
+RangeMatrix::RangeMatrix() : mpMat(NULL), mnCol1(-1), mnRow1(-1), mnCol2(-1), mnRow2(-1) {}
+
+bool RangeMatrix::isRangeValid() const
+{
+ return mnCol1 >= 0 && mnRow1 >= 0 && mnCol2 >= 0 && mnRow2 >= 0 && mnCol1 <= mnCol2 && mnRow1 <= mnRow2;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 8cf87b0..bb9f919 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -51,6 +51,12 @@ class ScToken;
class ScJumpMatrix;
struct ScRefCellValue;
+namespace sc {
+
+struct RangeMatrix;
+
+}
+
#define MAXSTACK (4096 / sizeof(formula::FormulaToken*))
class ScTokenStack
@@ -298,6 +304,7 @@ inline void MatrixDoubleRefToMatrix(); // if MatrixFormula: PopDoubleRefPus
// If MatrixFormula or ForceArray: ConvertMatrixParameters()
inline bool MatrixParameterConversion();
ScMatrixRef PopMatrix();
+sc::RangeMatrix PopRangeMatrix();
void QueryMatrixType(ScMatrixRef& xMat, short& rRetTypeExpr, sal_uLong& rRetIndexExpr);
void PushDouble(double nVal);
@@ -338,6 +345,8 @@ ScMatrixRef CreateMatrixFromDoubleRef( const formula::FormulaToken* pToken,
inline ScTokenMatrixMap& GetTokenMatrixMap();
ScTokenMatrixMap* CreateTokenMatrixMap();
ScMatrixRef GetMatrix();
+sc::RangeMatrix GetRangeMatrix();
+
void ScTableOp(); // repeated operations
void ScErrCell(); // special handling for
// error cell
@@ -373,7 +382,7 @@ double Compare();
/** @param pOptions
NULL means case sensitivity document option is to be used!
*/
-ScMatrixRef CompareMat( ScCompareOptions* pOptions = NULL );
+sc::RangeMatrix CompareMat( ScCompareOptions* pOptions = NULL );
ScMatrixRef QueryMat( const ScMatrixRef& pMat, ScCompareOptions& rOptions );
void ScEqual();
void ScNotEqual();
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index 4ac4b6b..40f4bef 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -93,7 +93,11 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
if (p2->IsStartFixed() && p2->IsEndFixed())
{
// Cached the converted token for absolute range referene.
- formula::FormulaTokenRef xTok(new ScMatrixToken(pMat));
+ ScComplexRefData aRef;
+ ScRange aRefRange = rTopPos;
+ aRefRange.aEnd.SetRow(rTopPos.Row() + nRowEnd);
+ aRef.InitRange(aRefRange);
+ formula::FormulaTokenRef xTok(new ScMatrixRangeToken(pMat, aRef));
aCachedTokens.insert(CachedTokensType::value_type(p, xTok));
aCode2.AddToken(*xTok);
}
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index a4d0d55..fb7b7dd 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -1081,11 +1081,11 @@ double ScInterpreter::Compare()
}
-ScMatrixRef ScInterpreter::CompareMat( ScCompareOptions* pOptions )
+sc::RangeMatrix ScInterpreter::CompareMat( ScCompareOptions* pOptions )
{
String aVal1, aVal2;
ScCompare aComp( &aVal1, &aVal2 );
- ScMatrixRef pMat[2];
+ sc::RangeMatrix aMat[2];
ScAddress aAdr;
for( short i = 1; i >= 0; i-- )
{
@@ -1127,11 +1127,11 @@ ScMatrixRef ScInterpreter::CompareMat( ScCompareOptions* pOptions )
break;
case svDoubleRef:
case svMatrix:
- pMat[ i ] = GetMatrix();
- if ( !pMat[ i ] )
+ aMat[i] = GetRangeMatrix();
+ if (!aMat[i].mpMat)
SetError( errIllegalParameter);
else
- pMat[i]->SetErrorInterpreter( NULL);
+ aMat[i].mpMat->SetErrorInterpreter(NULL);
// errors are transported as DoubleError inside matrix
break;
default:
@@ -1139,82 +1139,88 @@ ScMatrixRef ScInterpreter::CompareMat( ScCompareOptions* pOptions )
break;
}
}
- ScMatrixRef pResMat = NULL;
+
+ sc::RangeMatrix aRes;
if( !nGlobalError )
{
- if ( pMat[0] && pMat[1] )
+ if (aMat[0].mpMat && aMat[1].mpMat)
{
SCSIZE nC0, nC1;
SCSIZE nR0, nR1;
- pMat[0]->GetDimensions( nC0, nR0 );
- pMat[1]->GetDimensions( nC1, nR1 );
+ aMat[0].mpMat->GetDimensions(nC0, nR0);
+ aMat[1].mpMat->GetDimensions(nC1, nR1);
SCSIZE nC = std::max( nC0, nC1 );
SCSIZE nR = std::max( nR0, nR1 );
- pResMat = GetNewMat( nC, nR);
- if ( !pResMat )
- return NULL;
+ aRes.mpMat = GetNewMat( nC, nR);
+ if (!aRes.mpMat)
+ return aRes;
for ( SCSIZE j=0; j<nC; j++ )
{
for ( SCSIZE k=0; k<nR; k++ )
{
SCSIZE nCol = j, nRow = k;
- if ( pMat[0]->ValidColRowOrReplicated( nCol, nRow ) &&
- pMat[1]->ValidColRowOrReplicated( nCol, nRow ))
+ if (aMat[0].mpMat->ValidColRowOrReplicated(nCol, nRow) &&
+ aMat[1].mpMat->ValidColRowOrReplicated(nCol, nRow))
{
for ( short i=1; i>=0; i-- )
{
- if ( pMat[i]->IsString(j,k) )
+ if (aMat[i].mpMat->IsString(j, k))
{
aComp.bVal[i] = false;
- *aComp.pVal[i] = pMat[i]->GetString(j,k);
- aComp.bEmpty[i] = pMat[i]->IsEmpty(j,k);
+ *aComp.pVal[i] = aMat[i].mpMat->GetString(j, k);
+ aComp.bEmpty[i] = aMat[i].mpMat->IsEmpty(j, k);
}
else
{
aComp.bVal[i] = true;
- aComp.nVal[i] = pMat[i]->GetDouble(j,k);
+ aComp.nVal[i] = aMat[i].mpMat->GetDouble(j, k);
aComp.bEmpty[i] = false;
}
}
- pResMat->PutDouble( CompareFunc( aComp, pOptions ), j,k );
+ aRes.mpMat->PutDouble(CompareFunc(aComp, pOptions), j, k);
}
else
- pResMat->PutString( ScGlobal::GetRscString(STR_NO_VALUE), j,k );
+ aRes.mpMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), j, k);
}
}
}
- else if ( pMat[0] || pMat[1] )
+ else if (aMat[0].mpMat || aMat[1].mpMat)
{
- short i = ( pMat[0] ? 0 : 1);
+ short i = ( aMat[0].mpMat ? 0 : 1);
SCSIZE nC, nR;
- pMat[i]->GetDimensions( nC, nR );
- pResMat = GetNewMat( nC, nR);
- if ( !pResMat )
- return NULL;
+ aMat[i].mpMat->GetDimensions(nC, nR);
+ aRes.mpMat = GetNewMat( nC, nR);
+ if (!aRes.mpMat)
+ return aRes;
+
+ aRes.mnCol1 = aMat[i].mnCol1;
+ aRes.mnRow1 = aMat[i].mnRow1;
+ aRes.mnCol2 = aMat[i].mnCol2;
+ aRes.mnRow2 = aMat[i].mnRow2;
for (SCSIZE j = 0; j < nC; ++j)
{
for (SCSIZE k = 0; k < nR; ++k)
{
- if ( pMat[i]->IsValue(j,k) )
+ if (aMat[i].mpMat->IsValue(j, k))
{
aComp.bVal[i] = true;
- aComp.nVal[i] = pMat[i]->GetDouble(j,k);
+ aComp.nVal[i] = aMat[i].mpMat->GetDouble(j, k);
aComp.bEmpty[i] = false;
}
else
{
aComp.bVal[i] = false;
- *aComp.pVal[i] = pMat[i]->GetString(j,k);
- aComp.bEmpty[i] = pMat[i]->IsEmpty(j,k);
+ *aComp.pVal[i] = aMat[i].mpMat->GetString(j, k);
+ aComp.bEmpty[i] = aMat[i].mpMat->IsEmpty(j, k);
}
- pResMat->PutDouble( CompareFunc(aComp, pOptions), j, k);
+ aRes.mpMat->PutDouble(CompareFunc(aComp, pOptions), j, k);
}
}
}
}
nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
- return pResMat;
+ return aRes;
}
@@ -1228,7 +1234,7 @@ ScMatrixRef ScInterpreter::QueryMat( const ScMatrixRef& pMat, ScCompareOptions&
PushString(rItem.maString);
else
PushDouble(rItem.mfVal);
- ScMatrixRef pResultMatrix = CompareMat( &rOptions);
+ ScMatrixRef pResultMatrix = CompareMat( &rOptions).mpMat;
nCurFmtType = nSaveCurFmtType;
nFuncFmtType = nSaveFuncFmtType;
if (nGlobalError || !pResultMatrix)
@@ -1264,19 +1270,56 @@ ScMatrixRef ScInterpreter::QueryMat( const ScMatrixRef& pMat, ScCompareOptions&
return pResultMatrix;
}
+namespace {
+
+double applyImplicitIntersection(const sc::RangeMatrix& rMat, const ScAddress& rPos)
+{
+ if (rMat.mnRow1 <= rPos.Row() && rPos.Row() <= rMat.mnRow2 && rMat.mnCol1 == rMat.mnCol2)
+ {
+ SCROW nOffset = rPos.Row() - rMat.mnRow1;
+ return rMat.mpMat->GetDouble(0, nOffset);
+ }
+
+ if (rMat.mnCol1 <= rPos.Col() && rPos.Col() <= rMat.mnCol2 && rMat.mnRow1 == rMat.mnRow2)
+ {
+ SCROW nOffset = rPos.Col() - rMat.mnCol1;
+ return rMat.mpMat->GetDouble(nOffset, 0);
+ }
+
+ double fVal;
+ rtl::math::setNan(&fVal);
+ return fVal;
+}
+
+}
void ScInterpreter::ScEqual()
{
if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
{
- ScMatrixRef pMat = CompareMat();
- if ( !pMat )
+ sc::RangeMatrix aMat = CompareMat();
+ if (!aMat.mpMat)
+ {
PushIllegalParameter();
- else
+ return;
+ }
+
+ if (aMat.isRangeValid())
{
- pMat->CompareEqual();
- PushMatrix( pMat );
+ // This matrix represents a range reference. Apply implicit intersection.
+ double fVal = applyImplicitIntersection(aMat, aPos);
+ if (rtl::math::isNan(fVal))
+ {
+ PushError(errCellNoValue);
+ return;
+ }
+
+ PushInt(fVal == 0.0);
+ return;
}
+
+ aMat.mpMat->CompareEqual();
+ PushMatrix(aMat.mpMat);
}
else
PushInt( Compare() == 0 );
@@ -1287,14 +1330,29 @@ void ScInterpreter::ScNotEqual()
{
if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
{
- ScMatrixRef pMat = CompareMat();
- if ( !pMat )
+ sc::RangeMatrix aMat = CompareMat();
+ if (!aMat.mpMat)
+ {
PushIllegalParameter();
- else
+ return;
+ }
+
+ if (aMat.isRangeValid())
{
- pMat->CompareNotEqual();
- PushMatrix( pMat );
+ // This matrix represents a range reference. Apply implicit intersection.
+ double fVal = applyImplicitIntersection(aMat, aPos);
+ if (rtl::math::isNan(fVal))
+ {
+ PushError(errCellNoValue);
+ return;
+ }
+
+ PushInt(fVal != 0.0);
+ return;
}
+
+ aMat.mpMat->CompareNotEqual();
+ PushMatrix(aMat.mpMat);
}
else
PushInt( Compare() != 0 );
@@ -1305,14 +1363,29 @@ void ScInterpreter::ScLess()
{
if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
{
- ScMatrixRef pMat = CompareMat();
- if ( !pMat )
+ sc::RangeMatrix aMat = CompareMat();
+ if (!aMat.mpMat)
+ {
PushIllegalParameter();
- else
+ return;
+ }
+
+ if (aMat.isRangeValid())
{
- pMat->CompareLess();
- PushMatrix( pMat );
+ // This matrix represents a range reference. Apply implicit intersection.
+ double fVal = applyImplicitIntersection(aMat, aPos);
+ if (rtl::math::isNan(fVal))
+ {
+ PushError(errCellNoValue);
+ return;
+ }
+
+ PushInt(fVal < 0.0);
+ return;
}
+
+ aMat.mpMat->CompareLess();
+ PushMatrix(aMat.mpMat);
}
else
PushInt( Compare() < 0 );
@@ -1323,14 +1396,29 @@ void ScInterpreter::ScGreater()
{
if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
{
- ScMatrixRef pMat = CompareMat();
- if ( !pMat )
+ sc::RangeMatrix aMat = CompareMat();
+ if (!aMat.mpMat)
+ {
PushIllegalParameter();
- else
+ return;
+ }
+
+ if (aMat.isRangeValid())
{
- pMat->CompareGreater();
- PushMatrix( pMat );
+ // This matrix represents a range reference. Apply implicit intersection.
+ double fVal = applyImplicitIntersection(aMat, aPos);
+ if (rtl::math::isNan(fVal))
+ {
+ PushError(errCellNoValue);
+ return;
+ }
+
+ PushInt(fVal > 0.0);
+ return;
}
+
+ aMat.mpMat->CompareGreater();
+ PushMatrix(aMat.mpMat);
}
else
PushInt( Compare() > 0 );
@@ -1341,14 +1429,29 @@ void ScInterpreter::ScLessEqual()
{
if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
{
- ScMatrixRef pMat = CompareMat();
- if ( !pMat )
+ sc::RangeMatrix aMat = CompareMat();
+ if (!aMat.mpMat)
+ {
PushIllegalParameter();
- else
+ return;
+ }
+
+ if (aMat.isRangeValid())
{
- pMat->CompareLessEqual();
- PushMatrix( pMat );
+ // This matrix represents a range reference. Apply implicit intersection.
+ double fVal = applyImplicitIntersection(aMat, aPos);
+ if (rtl::math::isNan(fVal))
+ {
+ PushError(errCellNoValue);
+ return;
+ }
+
+ PushInt(fVal <= 0.0);
+ return;
}
+
+ aMat.mpMat->CompareLessEqual();
+ PushMatrix(aMat.mpMat);
}
else
PushInt( Compare() <= 0 );
@@ -1359,14 +1462,29 @@ void ScInterpreter::ScGreaterEqual()
{
if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
{
- ScMatrixRef pMat = CompareMat();
- if ( !pMat )
+ sc::RangeMatrix aMat = CompareMat();
+ if (!aMat.mpMat)
+ {
PushIllegalParameter();
- else
+ return;
+ }
+
+ if (aMat.isRangeValid())
{
- pMat->CompareGreaterEqual();
- PushMatrix( pMat );
+ // This matrix represents a range reference. Apply implicit intersection.
+ double fVal = applyImplicitIntersection(aMat, aPos);
+ if (rtl::math::isNan(fVal))
+ {
+ PushError(errCellNoValue);
+ return;
+ }
+
+ PushInt(fVal >= 0.0);
+ return;
}
+
+ aMat.mpMat->CompareGreaterEqual();
+ PushMatrix(aMat.mpMat);
}
else
PushInt( Compare() >= 0 );
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index c6025d4..7beb580 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -1794,6 +1794,45 @@ ScMatrixRef ScInterpreter::PopMatrix()
return NULL;
}
+sc::RangeMatrix ScInterpreter::PopRangeMatrix()
+{
+ sc::RangeMatrix aRet;
+ if (sp)
+ {
+ switch (pStack[sp-1]->GetType())
+ {
+ case svMatrix:
+ {
+ --sp;
+ FormulaToken* p = pStack[sp];
+ ScToken* p2 = static_cast<ScToken*>(p);
+ aRet.mpMat = p2->GetMatrix();
+ if (aRet.mpMat)
+ {
+ aRet.mpMat->SetErrorInterpreter(this);
+ if (p2->GetByte() == MATRIX_TOKEN_HAS_RANGE)
+ {
+ const ScComplexRefData& rRef = p2->GetDoubleRef();
+ if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() && !rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel())
+ {
+ aRet.mnCol1 = rRef.Ref1.Col();
+ aRet.mnRow1 = rRef.Ref1.Row();
+ aRet.mnCol2 = rRef.Ref2.Col();
+ aRet.mnRow2 = rRef.Ref2.Row();
+ }
+ }
+ }
+ else
+ SetError( errUnknownVariable);
+ }
+ break;
+ default:
+ aRet.mpMat = PopMatrix();
+ }
+ }
+ return aRet;
+}
+
void ScInterpreter::QueryMatrixType(ScMatrixRef& xMat, short& rRetTypeExpr, sal_uLong& rRetIndexExpr)
{
if (xMat)
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index ad7d799..a033693 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -494,6 +494,20 @@ ScMatrixRef ScInterpreter::GetMatrix()
return pMat;
}
+sc::RangeMatrix ScInterpreter::GetRangeMatrix()
+{
+ sc::RangeMatrix aRet;
+ switch (GetRawStackType())
+ {
+ case svMatrix:
+ aRet = PopRangeMatrix();
+ break;
+ default:
+ aRet.mpMat = GetMatrix();
+ }
+ return aRet;
+}
+
void ScInterpreter::ScMatValue()
{
if ( MustHaveParamCount( GetByte(), 3 ) )
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index e5627ff..9f5a7e6 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -804,6 +804,47 @@ bool ScMatrixToken::operator==( const FormulaToken& r ) const
return FormulaToken::operator==( r ) && pMatrix == static_cast<const ScToken&>(r).GetMatrix();
}
+ScMatrixRangeToken::ScMatrixRangeToken( const ScMatrixRef& p, const ScComplexRefData& rRef ) :
+ ScToken(formula::svMatrix), mpMatrix(p), maRef(rRef) {}
+
+ScMatrixRangeToken::ScMatrixRangeToken( const ScMatrixRangeToken& r ) :
+ ScToken(r), mpMatrix(r.mpMatrix), maRef(r.maRef) {}
+
+sal_uInt8 ScMatrixRangeToken::GetByte() const
+{
+ return MATRIX_TOKEN_HAS_RANGE;
+}
+
+const ScMatrix* ScMatrixRangeToken::GetMatrix() const
+{
+ return mpMatrix.get();
+}
+
+ScMatrix* ScMatrixRangeToken::GetMatrix()
+{
+ return mpMatrix.get();
+}
+
+const ScComplexRefData& ScMatrixRangeToken::GetDoubleRef() const
+{
+ return maRef;
+}
+
+ScComplexRefData& ScMatrixRangeToken::GetDoubleRef()
+{
+ return maRef;
+}
+
+bool ScMatrixRangeToken::operator==( const FormulaToken& r ) const
+{
+ return FormulaToken::operator==(r) && mpMatrix == static_cast<const ScToken&>(r).GetMatrix();
+}
+
+FormulaToken* ScMatrixRangeToken::Clone() const
+{
+ return new ScMatrixRangeToken(*this);
+}
+
// ============================================================================
ScExternalSingleRefToken::ScExternalSingleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& r ) :
More information about the Libreoffice-commits
mailing list