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.yosh...@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.yosh...@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 ) : _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits