[Libreoffice-commits] core.git: Branch 'feature/calc-group-interpreter-2' - 2 commits - formula/source include/formula sc/inc sc/Library_sc.mk sc/source
Kohei Yoshida
kohei.yoshida at gmail.com
Thu Sep 5 08:08:28 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 | 24 +++
sc/inc/types.hxx | 13 +
sc/source/core/data/column2.cxx | 61 ++++---
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 | 24 +++
sc/source/core/inc/interpre.hxx | 11 +
sc/source/core/opencl/formulagroupcl.cxx | 22 +-
sc/source/core/tool/formulagroup.cxx | 31 +++
sc/source/core/tool/interpr1.cxx | 244 ++++++++++++++++++++++---------
sc/source/core/tool/interpr4.cxx | 39 ++++
sc/source/core/tool/interpr5.cxx | 14 +
sc/source/core/tool/token.cxx | 41 +++++
21 files changed, 489 insertions(+), 136 deletions(-)
New commits:
commit 319dd18f82aeb42dc3cdb49652211ebdbff14d25
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 49cc24a..f1b53c3 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 c74c6c8..b6491cc 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -48,6 +48,8 @@
#include <boost/scoped_ptr.hpp>
namespace editeng { class SvxBorderLine; }
+namespace formula { struct VectorRefArray; }
+
namespace sc {
struct FormulaGroupContext;
class StartListeningContext;
@@ -57,6 +59,7 @@ namespace sc {
struct ColumnBlockPosition;
struct RefUpdateContext;
}
+
class SvxFontItem;
class KeyEvent;
@@ -1987,7 +1990,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 06e8151..d36e183 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;
@@ -851,7 +852,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 b22b477..5c5e28a 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>
@@ -2065,7 +2066,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;
@@ -2161,10 +2162,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);
@@ -2175,23 +2176,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:
@@ -2199,8 +2203,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);
@@ -2222,13 +2226,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
@@ -2245,7 +2249,7 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
rCell.SetErrCode(0);
rCell.SetDirtyVar();
}
- return NULL;
+ return formula::VectorRefArray();
}
rArray.push_back(fVal);
@@ -2254,9 +2258,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:
@@ -2264,27 +2281,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 db97f77..7bf5c66 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 64173c9..1c74667 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3396,11 +3396,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
@@ -3444,7 +3444,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;
@@ -3457,11 +3457,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 a835c46..daa0dcc 100644
--- a/sc/source/core/opencl/formulagroupcl.cxx
+++ b/sc/source/core/opencl/formulagroupcl.cxx
@@ -792,7 +792,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();
@@ -801,7 +801,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));
@@ -815,7 +815,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;
@@ -830,7 +830,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)
@@ -884,7 +884,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)
@@ -892,7 +892,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));
@@ -907,7 +907,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 ) );
@@ -915,7 +915,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 ) );
}
@@ -1004,11 +1004,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();
@@ -1022,7 +1022,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 63b106dbfe66b0562ca3d8739aad1ea124084aea
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 83e3358..5465960 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -180,6 +180,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 a7491a2..64173c9 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3529,7 +3529,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 da14d42..fd1d224 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