formula/source/core/api/vectortoken.cxx | 2 include/formula/vectortoken.hxx | 4 sc/inc/column.hxx | 1 sc/inc/document.hxx | 12 ++ sc/inc/formulacell.hxx | 1 sc/inc/formulagroup.hxx | 7 + sc/inc/formularesult.hxx | 1 sc/inc/table.hxx | 2 sc/source/core/data/column2.cxx | 186 +++++++++++++++++++++++++------ sc/source/core/data/document.cxx | 9 + sc/source/core/data/formulacell.cxx | 40 ++++++ sc/source/core/data/table1.cxx | 15 ++ sc/source/core/opencl/formulagroupcl.cxx | 33 ++--- sc/source/core/tool/formulagroup.cxx | 142 ++++++++++++++++++++++- sc/source/core/tool/formularesult.cxx | 49 ++++++++ sc/source/core/tool/interpr6.cxx | 2 16 files changed, 442 insertions(+), 64 deletions(-)
New commits: commit a66aeace78f366800ba5bc8be0d334ea823179ab Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Tue Sep 10 11:16:22 2013 -0400 Add ability to specify starting row when querying for last non-empty row. And it can only go upwards from there. Change-Id: I4c8037f687dfdd0b6c937463696d628e78e4a8bf diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index ba79c23..6d09ad1 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -184,6 +184,7 @@ public: bool HasVisibleDataAt(SCROW nRow) const; SCROW GetFirstDataPos() const; SCROW GetLastDataPos() const; + SCROW GetLastDataPos( SCROW nLastRow ) const; bool GetPrevDataPos(SCROW& rRow) const; bool GetNextDataPos(SCROW& rRow) const; void FindDataAreaPos(SCROW& rRow, bool bDown) const; // (without Broadcaster) diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 4cbf06a..6993abb 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -1028,11 +1028,16 @@ public: SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const; /** - * Return the last non-empty row position in given columns, or 0 if the - * columns are empty. A negative value is returned if the given sheet or - * column positions are invalid. + * Return the last non-empty row position in given columns that's no + * greater than the initial last row position, or 0 if the columns are + * empty. A negative value is returned if the given sheet or column + * positions are invalid. + * + * <p>It starts from the specified last row position, and finds the first + * non-empty row position in the upward direction if the start row + * position is empty.</p> */ - SCROW GetLastDataRow( SCTAB nTab, SCCOL nCol1, SCCOL nCol2 ) const; + SCROW GetLastDataRow( SCTAB nTab, SCCOL nCol1, SCCOL nCol2, SCROW nLastRow ) const; SC_DLLPUBLIC void GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bIncludeOld, bool bOnlyDown ) const; diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 9bf3f90..fc8ae3a 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -469,7 +469,7 @@ public: bool ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const; - SCROW GetLastDataRow( SCCOL nCol1, SCCOL nCol2 ) const; + SCROW GetLastDataRow( SCCOL nCol1, SCCOL nCol2, SCROW nLastRow ) const; SCSIZE GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScDirection eDir ) const; diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 42c5469..eda83ff 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -1255,6 +1255,19 @@ SCROW ScColumn::GetLastDataPos() const return MAXROW - static_cast<SCROW>(it->size); } +SCROW ScColumn::GetLastDataPos( SCROW nLastRow ) const +{ + sc::CellStoreType::const_position_type aPos = maCells.position(nLastRow); + if (aPos.first->type != sc::element_type_empty) + return nLastRow; + + if (aPos.first == maCells.begin()) + // This is the first block, and is empty. + return 0; + + return static_cast<SCROW>(aPos.first->position - 1); +} + bool ScColumn::GetPrevDataPos(SCROW& rRow) const { std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(rRow); diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 7bda1da..dc7db44 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -1018,13 +1018,13 @@ bool ScDocument::ShrinkToUsedDataArea( bool& o_bShrunk, SCTAB nTab, SCCOL& rStar return maTabs[nTab]->ShrinkToUsedDataArea( o_bShrunk, rStartCol, rStartRow, rEndCol, rEndRow, bColumnsOnly); } -SCROW ScDocument::GetLastDataRow( SCTAB nTab, SCCOL nCol1, SCCOL nCol2 ) const +SCROW ScDocument::GetLastDataRow( SCTAB nTab, SCCOL nCol1, SCCOL nCol2, SCROW nLastRow ) const { const ScTable* pTab = FetchTable(nTab); if (!pTab) return -1; - return pTab->GetLastDataRow(nCol1, nCol2); + return pTab->GetLastDataRow(nCol1, nCol2, nLastRow); } // connected area diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index b659409..249e442 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -3365,7 +3365,8 @@ class GroupTokenConverter SCROW trimLength(SCTAB nTab, SCCOL nCol1, SCCOL nCol2, SCROW nRow, SCROW nRowLen) { - SCROW nLastRow = mrDoc.GetLastDataRow(nTab, nCol1, nCol2); + SCROW nLastRow = nRow + nRowLen - 1; // current last row. + nLastRow = mrDoc.GetLastDataRow(nTab, nCol1, nCol2, nLastRow); if (nLastRow < (nRow + nRowLen - 1)) nRowLen = nLastRow - nRow + 1; else if (nLastRow == 0) diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index 9af12d6..f827cc9 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -987,20 +987,20 @@ bool ScTable::ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rS (rStartRow != rEndRow || aCol[rStartCol].HasDataAt( rStartRow))); } -SCROW ScTable::GetLastDataRow( SCCOL nCol1, SCCOL nCol2 ) const +SCROW ScTable::GetLastDataRow( SCCOL nCol1, SCCOL nCol2, SCROW nLastRow ) const { if (!ValidCol(nCol1) || !ValidCol(nCol2)) return -1; - SCROW nLastRow = 0; + SCROW nNewLastRow = 0; for (SCCOL i = nCol1; i <= nCol2; ++i) { - SCROW nThis = aCol[i].GetLastDataPos(); - if (nLastRow < nThis) - nLastRow = nThis; + SCROW nThis = aCol[i].GetLastDataPos(nLastRow); + if (nNewLastRow < nThis) + nNewLastRow = nThis; } - return nLastRow; + return nNewLastRow; } SCSIZE ScTable::GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, commit de746be2078c191692d94d11006564ec60090b7d Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Tue Sep 10 09:17:12 2013 -0400 Oops I forgot a return statement. Change-Id: Ifdea804b178ccf5c25ef21fba2642f31a90e4061 diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index d161910..7bda1da 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -1024,7 +1024,7 @@ SCROW ScDocument::GetLastDataRow( SCTAB nTab, SCCOL nCol1, SCCOL nCol2 ) const if (!pTab) return -1; - pTab->GetLastDataRow(nCol1, nCol2); + return pTab->GetLastDataRow(nCol1, nCol2); } // connected area commit d466bd65be615516ee5402915abb26e4f3775e23 Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Tue Sep 10 00:11:13 2013 -0400 Fix several logic errors in required array size calculation. Change-Id: Ife05e21583d14c873d38c09d78e964cdb3817d6c diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index be9fd90..b659409 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -3440,7 +3440,7 @@ public: case svDoubleRef: { ScComplexRefData aRef = pToken->GetDoubleRef(); - ScRange aAbs = aRef.toAbs(mrCell.aPos); + ScRange aAbs = aRef.toAbs(mrPos); // Check for self reference. if (aRef.Ref1.IsRowRel()) @@ -3466,12 +3466,16 @@ public: size_t nCols = aAbs.aEnd.Col() - aAbs.aStart.Col() + 1; std::vector<formula::VectorRefArray> aArrays; aArrays.reserve(nCols); - SCROW nArrayLength = nLen; SCROW nRefRowSize = aAbs.aEnd.Row() - aAbs.aStart.Row() + 1; + SCROW nArrayLength = nRefRowSize; if (!bAbsLast) { // range end position is relative. Extend the array length. - nArrayLength += nRefRowSize - 1; + SCROW nLastRefRowOffset = aAbs.aEnd.Row() - mrPos.Row(); + SCROW nLastRefRow = mrPos.Row() + nLen - 1 + nLastRefRowOffset; + SCROW nNewLength = nLastRefRow - aAbs.aStart.Row() + 1; + if (nNewLength > nArrayLength) + nArrayLength = nNewLength; } // Trim trailing empty rows. diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx index 5dff3d9..1dbe5bd 100644 --- a/sc/source/core/tool/formulagroup.cxx +++ b/sc/source/core/tool/formulagroup.cxx @@ -204,9 +204,14 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres nRowEnd += i; size_t nRowSize = nRowEnd - nRowStart + 1; ScMatrixRef pMat(new ScMatrix(nColSize, nRowSize)); - if (p2->GetArrayLength() < nRowSize) - // Data array is shorter than the row size of the reference. Truncate it. - nRowSize = p2->GetArrayLength(); + + size_t nDataRowEnd = p2->GetArrayLength() - 1; + if (nRowStart > nDataRowEnd) + // Referenced rows are all empty. + nRowSize = 0; + else if (nRowEnd > nDataRowEnd) + // Data array is shorter than the row size of the reference. Truncate it to the data. + nRowSize -= nRowEnd - nDataRowEnd; for (size_t nCol = 0; nCol < nColSize; ++nCol) { commit ae0d98e18125ecd3fa92f4612a62da32c704579d Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Sep 9 23:14:19 2013 -0400 Trim data array length to remove trailing empty rows. Change-Id: I61a6a289ad1c2c757fcea490ada5d40fee08e840 diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 6949b6d..4cbf06a 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -1027,6 +1027,13 @@ public: SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const; + /** + * Return the last non-empty row position in given columns, or 0 if the + * columns are empty. A negative value is returned if the given sheet or + * column positions are invalid. + */ + SCROW GetLastDataRow( SCTAB nTab, SCCOL nCol1, SCCOL nCol2 ) const; + SC_DLLPUBLIC void GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bIncludeOld, bool bOnlyDown ) const; SC_DLLPUBLIC bool GetCellArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const; diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 8816642..9bf3f90 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -469,6 +469,8 @@ public: bool ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const; + SCROW GetLastDataRow( SCCOL nCol1, SCCOL nCol2 ) const; + SCSIZE GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScDirection eDir ) const; diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index c6d3c79..d161910 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -1018,6 +1018,15 @@ bool ScDocument::ShrinkToUsedDataArea( bool& o_bShrunk, SCTAB nTab, SCCOL& rStar return maTabs[nTab]->ShrinkToUsedDataArea( o_bShrunk, rStartCol, rStartRow, rEndCol, rEndRow, bColumnsOnly); } +SCROW ScDocument::GetLastDataRow( SCTAB nTab, SCCOL nCol1, SCCOL nCol2 ) const +{ + const ScTable* pTab = FetchTable(nTab); + if (!pTab) + return -1; + + pTab->GetLastDataRow(nCol1, nCol2); +} + // connected area void ScDocument::GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 87a3d05..be9fd90 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -3362,6 +3362,18 @@ class GroupTokenConverter return true; } + + SCROW trimLength(SCTAB nTab, SCCOL nCol1, SCCOL nCol2, SCROW nRow, SCROW nRowLen) + { + SCROW nLastRow = mrDoc.GetLastDataRow(nTab, nCol1, nCol2); + if (nLastRow < (nRow + nRowLen - 1)) + nRowLen = nLastRow - nRow + 1; + else if (nLastRow == 0) + // Column is empty. + nRowLen = 1; + + return nRowLen; + } public: GroupTokenConverter(sc::FormulaGroupContext& rCxt, ScTokenArray& rGroupTokens, ScDocument& rDoc, ScFormulaCell& rCell, const ScAddress& rPos) : mrCxt(rCxt), mrGroupTokens(rGroupTokens), mrDoc(rDoc), mrCell(rCell), mrPos(rPos) {} @@ -3397,6 +3409,9 @@ public: if (isSelfReferenceRelative(aRefPos, aRef.Row())) return false; + // Trim data array length to actual data range. + nLen = trimLength(aRefPos.Tab(), aRefPos.Col(), aRefPos.Col(), aRefPos.Row(), nLen); + // Fetch double array guarantees that the length of the // returned array equals or greater than the requested // length. @@ -3459,6 +3474,9 @@ public: nArrayLength += nRefRowSize - 1; } + // Trim trailing empty rows. + nArrayLength = trimLength(aRefPos.Tab(), aAbs.aStart.Col(), aAbs.aEnd.Col(), aRefPos.Row(), nArrayLength); + for (SCCOL i = aAbs.aStart.Col(); i <= aAbs.aEnd.Col(); ++i) { aRefPos.SetCol(i); diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index 6391eee..9af12d6 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -987,6 +987,21 @@ bool ScTable::ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rS (rStartRow != rEndRow || aCol[rStartCol].HasDataAt( rStartRow))); } +SCROW ScTable::GetLastDataRow( SCCOL nCol1, SCCOL nCol2 ) const +{ + if (!ValidCol(nCol1) || !ValidCol(nCol2)) + return -1; + + SCROW nLastRow = 0; + for (SCCOL i = nCol1; i <= nCol2; ++i) + { + SCROW nThis = aCol[i].GetLastDataPos(); + if (nLastRow < nThis) + nLastRow = nThis; + } + + return nLastRow; +} SCSIZE ScTable::GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScDirection eDir ) const commit 71958acc9c6650606e59321b9b9aaf8c11ef907f Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Sep 9 20:39:17 2013 -0400 Eliminate (almost) duplicate code blocks. Change-Id: Ib5d0fae3efda6bde056f7e4990de57c8b3541549 diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 048402f..42c5469 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -2050,6 +2050,26 @@ void ScColumn::FillMatrix( ScMatrix& rMat, size_t nMatCol, SCROW nRow1, SCROW nR namespace { +template<typename _Blk> +void getBlockIterators( + sc::CellStoreType::iterator it, size_t& rLenRemain, + typename _Blk::iterator& rData, typename _Blk::iterator& rDataEnd ) +{ + rData = _Blk::begin(*it->data); + if (rLenRemain >= it->size) + { + // Block is shorter than the remaining requested length. + rDataEnd = _Blk::end(*it->data); + rLenRemain -= it->size; + } + else + { + rDataEnd = rData; + std::advance(rDataEnd, rLenRemain); + rLenRemain = 0; + } +} + bool appendDouble( sc::FormulaGroupContext::NumArrayType& rArray, size_t nLen, sc::CellStoreType::iterator it, const sc::CellStoreType::iterator& itEnd ) @@ -2064,20 +2084,8 @@ bool appendDouble( { case sc::element_type_numeric: { - sc::numeric_block::iterator itData = sc::numeric_block::begin(*it->data); - sc::numeric_block::iterator itDataEnd; - if (nLenRemain >= it->size) - { - // Block is shorter than the remaining requested length. - itDataEnd = sc::numeric_block::end(*it->data); - nLenRemain -= it->size; - } - else - { - itDataEnd = itData; - std::advance(itDataEnd, nLenRemain); - nLenRemain = 0; - } + sc::numeric_block::iterator itData, itDataEnd; + getBlockIterators<sc::numeric_block>(it, nLenRemain, itData, itDataEnd); for (; itData != itDataEnd; ++itData) rArray.push_back(*itData); @@ -2085,20 +2093,8 @@ bool appendDouble( break; case sc::element_type_formula: { - sc::formula_block::iterator itData = sc::formula_block::begin(*it->data); - sc::formula_block::iterator itDataEnd; - if (nLenRemain >= it->size) - { - // Block is shorter than the remaining requested length. - itDataEnd = sc::formula_block::end(*it->data); - nLenRemain -= it->size; - } - else - { - itDataEnd = itData; - std::advance(itDataEnd, nLenRemain); - nLenRemain = 0; - } + sc::formula_block::iterator itData, itDataEnd; + getBlockIterators<sc::formula_block>(it, nLenRemain, itData, itDataEnd); sal_uInt16 nErr; double fVal; @@ -2161,20 +2157,8 @@ bool appendStrings( { case sc::element_type_string: { - sc::string_block::iterator itData = sc::string_block::begin(*it->data); - sc::string_block::iterator itDataEnd; - if (nLenRemain >= it->size) - { - // Block is shorter than the remaining requested length. - itDataEnd = sc::string_block::end(*it->data); - nLenRemain -= it->size; - } - else - { - itDataEnd = itData; - std::advance(itDataEnd, nLenRemain); - nLenRemain = 0; - } + sc::string_block::iterator itData, itDataEnd; + getBlockIterators<sc::string_block>(it, nLenRemain, itData, itDataEnd); for (; itData != itDataEnd; ++itData) rArray.push_back(rCxt.intern(*itData)); @@ -2182,20 +2166,8 @@ bool appendStrings( break; case sc::element_type_edittext: { - sc::edittext_block::iterator itData = sc::edittext_block::begin(*it->data); - sc::edittext_block::iterator itDataEnd; - if (nLenRemain >= it->size) - { - // Block is shorter than the remaining requested length. - itDataEnd = sc::edittext_block::end(*it->data); - nLenRemain -= it->size; - } - else - { - itDataEnd = itData; - std::advance(itDataEnd, nLenRemain); - nLenRemain = 0; - } + sc::edittext_block::iterator itData, itDataEnd; + getBlockIterators<sc::edittext_block>(it, nLenRemain, itData, itDataEnd); for (; itData != itDataEnd; ++itData) { @@ -2206,20 +2178,8 @@ bool appendStrings( break; case sc::element_type_formula: { - sc::formula_block::iterator itData = sc::formula_block::begin(*it->data); - sc::formula_block::iterator itDataEnd; - if (nLenRemain >= it->size) - { - // Block is shorter than the remaining requested length. - itDataEnd = sc::formula_block::end(*it->data); - nLenRemain -= it->size; - } - else - { - itDataEnd = itData; - std::advance(itDataEnd, nLenRemain); - nLenRemain = 0; - } + sc::formula_block::iterator itData, itDataEnd; + getBlockIterators<sc::formula_block>(it, nLenRemain, itData, itDataEnd); sal_uInt16 nErr; OUString aStr; commit b951445113add8360a3efb97091faefb3c870ce5 Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Sep 9 19:36:30 2013 -0400 Support fetching string array that spans over multiple blocks. Change-Id: I543fca231e0be886159b8ddbd83ceffa1bf69c1b diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index 835eb91..a494759 100644 --- a/sc/inc/formulacell.hxx +++ b/sc/inc/formulacell.hxx @@ -252,6 +252,7 @@ public: sal_uInt16 GetErrCode(); // interpret first if necessary sal_uInt16 GetRawError(); // don't interpret, just return code or result error bool GetErrorOrValue( sal_uInt16& rErr, double& rVal ); + bool GetErrorOrString( sal_uInt16& rErr, OUString& rStr ); sal_uInt8 GetMatrixFlag() const; ScTokenArray* GetCode(); const ScTokenArray* GetCode() const; diff --git a/sc/inc/formularesult.hxx b/sc/inc/formularesult.hxx index 00cc9fd..4f13524 100644 --- a/sc/inc/formularesult.hxx +++ b/sc/inc/formularesult.hxx @@ -135,6 +135,7 @@ public: bool IsMultiline() const; bool GetErrorOrDouble( sal_uInt16& rErr, double& rVal ) const; + bool GetErrorOrString( sal_uInt16& rErr, OUString& rStr ) const; /** Get error code if set or GetCellResultType() is formula::svError or svUnknown, else 0. */ diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 7a97972..048402f 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -2148,6 +2148,138 @@ bool appendDouble( return false; } +bool appendStrings( + sc::FormulaGroupContext& rCxt, ScDocument* pDoc, + sc::FormulaGroupContext::StrArrayType& rArray, size_t nLen, + sc::CellStoreType::iterator it, const sc::CellStoreType::iterator& itEnd ) +{ + size_t nLenRemain = nLen; + + for (; it != itEnd; ++it) + { + switch (it->type) + { + case sc::element_type_string: + { + sc::string_block::iterator itData = sc::string_block::begin(*it->data); + sc::string_block::iterator itDataEnd; + if (nLenRemain >= it->size) + { + // Block is shorter than the remaining requested length. + itDataEnd = sc::string_block::end(*it->data); + nLenRemain -= it->size; + } + else + { + itDataEnd = itData; + std::advance(itDataEnd, nLenRemain); + nLenRemain = 0; + } + + for (; itData != itDataEnd; ++itData) + rArray.push_back(rCxt.intern(*itData)); + } + break; + case sc::element_type_edittext: + { + sc::edittext_block::iterator itData = sc::edittext_block::begin(*it->data); + sc::edittext_block::iterator itDataEnd; + if (nLenRemain >= it->size) + { + // Block is shorter than the remaining requested length. + itDataEnd = sc::edittext_block::end(*it->data); + nLenRemain -= it->size; + } + else + { + itDataEnd = itData; + std::advance(itDataEnd, nLenRemain); + nLenRemain = 0; + } + + for (; itData != itDataEnd; ++itData) + { + OUString aStr = ScEditUtil::GetString(**itData, pDoc); + rArray.push_back(rCxt.intern(aStr)); + } + } + break; + case sc::element_type_formula: + { + sc::formula_block::iterator itData = sc::formula_block::begin(*it->data); + sc::formula_block::iterator itDataEnd; + if (nLenRemain >= it->size) + { + // Block is shorter than the remaining requested length. + itDataEnd = sc::formula_block::end(*it->data); + nLenRemain -= it->size; + } + else + { + itDataEnd = itData; + std::advance(itDataEnd, nLenRemain); + nLenRemain = 0; + } + + sal_uInt16 nErr; + OUString aStr; + for (; itData != itDataEnd; ++itData) + { + ScFormulaCell& rFC = **itData; + if (!rFC.GetErrorOrString(nErr, aStr) || nErr) + { + if (nErr == ScErrorCodes::errCircularReference) + { + // This cell needs to be recalculated on next visit. + rFC.SetErrCode(0); + rFC.SetDirtyVar(); + } + return false; + } + + rArray.push_back(rCxt.intern(aStr)); + } + } + break; + case sc::element_type_empty: + { + // Fill it with NULL pointers. + if (nLenRemain >= it->size) + { + rArray.resize(rArray.size() + it->size, NULL); + nLenRemain -= it->size; + } + else + { + rArray.resize(rArray.size() + nLenRemain, NULL); + nLenRemain = 0; + } + } + break; + case sc::element_type_numeric: + default: + return false; + } + + if (!nLenRemain) + return true; + } + + return false; +} + +void copyFirstBlock( sc::FormulaGroupContext& rCxt, size_t nLen, const sc::CellStoreType::position_type& rPos ) +{ + rCxt.maStrArrays.push_back(new sc::FormulaGroupContext::StrArrayType); + sc::FormulaGroupContext::StrArrayType& rArray = rCxt.maStrArrays.back(); + rArray.reserve(nLen); + + const OUString* p = &sc::string_block::at(*rPos.first->data, rPos.second); + const OUString* pEnd = p + nLen; + for (; p != pEnd; ++p) + rArray.push_back(rCxt.intern(*p)); +} + } formula::VectorRefArray ScColumn::FetchVectorRefArray( sc::FormulaGroupContext& rCxt, SCROW nRow1, SCROW nRow2 ) @@ -2256,20 +2388,20 @@ formula::VectorRefArray ScColumn::FetchVectorRefArray( sc::FormulaGroupContext& if (nLenRequested <= nLen) { // Requested length fits a single block. - rCxt.maStrArrays.push_back(new sc::FormulaGroupContext::StrArrayType); + copyFirstBlock(rCxt, nLenRequested, aPos); sc::FormulaGroupContext::StrArrayType& rArray = rCxt.maStrArrays.back(); - rArray.reserve(nLenRequested); - - const OUString* p = &sc::string_block::at(*aPos.first->data, aPos.second); - const OUString* pEnd = p + nLenRequested; - for (; p != pEnd; ++p) - rArray.push_back(rCxt.intern(*p)); - return formula::VectorRefArray(&rArray[0]); } - // TODO: handle cases where the requested length goes beyond the - // current block just like we do with numeric array. + copyFirstBlock(rCxt, nLen, aPos); + sc::FormulaGroupContext::StrArrayType& rArray = rCxt.maStrArrays.back(); + + // Fill the remaining array with values from the following blocks. + ++aPos.first; + if (!appendStrings(rCxt, pDocument, rArray, nLenRequested - nLen, aPos.first, maCells.end())) + return formula::VectorRefArray(); + + return formula::VectorRefArray(&rArray[0]); } break; case sc::element_type_empty: diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 0f248a2..87a3d05 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2082,6 +2082,17 @@ bool ScFormulaCell::GetErrorOrValue( sal_uInt16& rErr, double& rVal ) return aResult.GetErrorOrDouble(rErr, rVal); } +bool ScFormulaCell::GetErrorOrString( sal_uInt16& rErr, OUString& rStr ) +{ + MaybeInterpret(); + + rErr = pCode->GetCodeError(); + if (rErr) + return true; + + return aResult.GetErrorOrString(rErr, rStr); +} + bool ScFormulaCell::HasOneReference( ScRange& r ) const { pCode->Reset(); diff --git a/sc/source/core/tool/formularesult.cxx b/sc/source/core/tool/formularesult.cxx index 511bfa5..ef6c15a 100644 --- a/sc/source/core/tool/formularesult.cxx +++ b/sc/source/core/tool/formularesult.cxx @@ -255,6 +255,19 @@ inline bool isValue( formula::StackVar sv ) || sv == formula::svEmptyCell || sv == formula::svHybridValueCell; } +inline bool isString( formula::StackVar sv ) +{ + switch (sv) + { + case formula::svString: + case formula::svHybridCell: + case formula::svHybridValueCell: + return true; + } + + return false; +} + } bool ScFormulaResult::IsValue() const @@ -321,6 +334,42 @@ bool ScFormulaResult::GetErrorOrDouble( sal_uInt16& rErr, double& rVal ) const return true; } +bool ScFormulaResult::GetErrorOrString( sal_uInt16& rErr, OUString& rStr ) const +{ + if (mnError) + { + rErr = mnError; + return true; + } + + formula::StackVar sv = GetCellResultType(); + if (sv == formula::svError) + { + if (GetType() == formula::svMatrixCell) + { + // don't need to test for mpToken here, GetType() already did it + rErr = static_cast<const ScMatrixCellResultToken*>(mpToken)-> + GetUpperLeftToken()->GetError(); + } + else if (mpToken) + { + rErr = mpToken->GetError(); + } + } + + if (rErr) + return true; + + if (!mbToken) + return false; + + if (!isString(sv)) + return false; + + rStr = GetString(); + return true; +} + sal_uInt16 ScFormulaResult::GetResultError() const { if (mnError) commit f8fe9f0f25787b9d73ec417dd06118e6a72b9631 Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Sep 9 18:53:33 2013 -0400 Move common code blocks to a function. Change-Id: I1b1aaa0b1dd8cc6e14fbac1981c67a8b63c92c2c diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx index 0b37b97..5dff3d9 100644 --- a/sc/source/core/tool/formulagroup.cxx +++ b/sc/source/core/tool/formulagroup.cxx @@ -83,6 +83,18 @@ void fillMatrix( ScMatrix& rMat, size_t nCol, const double* pNums, size_t nLen ) } } +void flushSegment( + ScMatrix& rMat, size_t nCol, rtl_uString** pHead, rtl_uString** pCur, rtl_uString** pTop ) +{ + size_t nOffset = pHead - pTop; + std::vector<OUString> aStrs; + aStrs.reserve(pCur - pHead); + for (; pHead != pCur; ++pHead) + aStrs.push_back(OUString(*pHead)); + + rMat.PutString(&aStrs[0], aStrs.size(), nCol, nOffset); +} + void fillMatrix( ScMatrix& rMat, size_t nCol, rtl_uString** pStrs, size_t nLen ) { rtl_uString** p = pStrs; @@ -102,13 +114,7 @@ void fillMatrix( ScMatrix& rMat, size_t nCol, rtl_uString** pStrs, size_t nLen ) if (pHead) { // Flush this non-empty segment to the matrix. - size_t nOffset = pHead - pStrs; - std::vector<OUString> aStrs; - aStrs.reserve(p - pHead); - for (; pHead != p; ++pHead) - aStrs.push_back(OUString(*pHead)); - - rMat.PutString(&aStrs[0], aStrs.size(), nCol, nOffset); + flushSegment(rMat, nCol, pHead, p, pStrs); pHead = NULL; } } @@ -116,13 +122,7 @@ void fillMatrix( ScMatrix& rMat, size_t nCol, rtl_uString** pStrs, size_t nLen ) if (pHead) { // Flush last non-empty segment to the matrix. - size_t nOffset = pHead - pStrs; - std::vector<OUString> aStrs; - aStrs.reserve(p - pHead); - for (; pHead != p; ++pHead) - aStrs.push_back(OUString(*pHead)); - - rMat.PutString(&aStrs[0], aStrs.size(), nCol, nOffset); + flushSegment(rMat, nCol, pHead, p, pStrs); } } commit 7d0f3695a20df18f5f6e609f70b8d1ef7825302b Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Sep 9 18:00:08 2013 -0400 Correctly handle empty cells for string arrays too. Because we need to make a distinction between an empty cell and a string cell containing zero-length string, I decided to switch to using rtl_uString* array and use NULL values as empty cells. Change-Id: I5bedb593507f34782e41a8a900602d445e5b1f6f diff --git a/formula/source/core/api/vectortoken.cxx b/formula/source/core/api/vectortoken.cxx index 557e0c0..b752f5d 100644 --- a/formula/source/core/api/vectortoken.cxx +++ b/formula/source/core/api/vectortoken.cxx @@ -13,7 +13,7 @@ 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) {} +VectorRefArray::VectorRefArray( rtl_uString** pArray ) : mpStringArray(pArray), mbNumeric(false) {} SingleVectorRefToken::SingleVectorRefToken( const double* pArray, size_t nLength ) : FormulaToken(svSingleVectorRef, ocPush), maArray(pArray), mnArrayLength(nLength) {} diff --git a/include/formula/vectortoken.hxx b/include/formula/vectortoken.hxx index 5186ca5..9bc82f3 100644 --- a/include/formula/vectortoken.hxx +++ b/include/formula/vectortoken.hxx @@ -18,14 +18,14 @@ struct FORMULA_DLLPUBLIC VectorRefArray { union { const double* mpNumericArray; - const OUString* mpStringArray; + rtl_uString** mpStringArray; }; bool mbNumeric; VectorRefArray(); VectorRefArray( const double* pArray ); - VectorRefArray( const OUString* pArray ); + VectorRefArray( rtl_uString** pArray ); }; /** diff --git a/sc/inc/formulagroup.hxx b/sc/inc/formulagroup.hxx index 776b24d..f57b237 100644 --- a/sc/inc/formulagroup.hxx +++ b/sc/inc/formulagroup.hxx @@ -15,6 +15,7 @@ #include <boost/noncopyable.hpp> #include <boost/ptr_container/ptr_vector.hpp> +#include <boost/unordered_set.hpp> class ScDocument; class ScTokenArray; @@ -23,13 +24,17 @@ namespace sc { struct FormulaGroupContext : boost::noncopyable { + typedef boost::unordered_set<OUString, OUStringHash> StrHashType; typedef std::vector<double> NumArrayType; - typedef std::vector<OUString> StrArrayType; + typedef std::vector<rtl_uString*> StrArrayType; typedef boost::ptr_vector<NumArrayType> NumArrayStoreType; typedef boost::ptr_vector<StrArrayType> StrArrayStoreType; + StrHashType maStrPool; NumArrayStoreType maNumArrays; StrArrayStoreType maStrArrays; + + rtl_uString* intern( const OUString& rStr ); }; /** diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 34ecbb2..7a97972 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -2256,8 +2256,16 @@ formula::VectorRefArray ScColumn::FetchVectorRefArray( sc::FormulaGroupContext& if (nLenRequested <= nLen) { // Requested length fits a single block. + rCxt.maStrArrays.push_back(new sc::FormulaGroupContext::StrArrayType); + sc::FormulaGroupContext::StrArrayType& rArray = rCxt.maStrArrays.back(); + rArray.reserve(nLenRequested); + const OUString* p = &sc::string_block::at(*aPos.first->data, aPos.second); - return formula::VectorRefArray(p); + const OUString* pEnd = p + nLenRequested; + for (; p != pEnd; ++p) + rArray.push_back(rCxt.intern(*p)); + + return formula::VectorRefArray(&rArray[0]); } // TODO: handle cases where the requested length goes beyond the diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx index f6a1dff..0b37b97 100644 --- a/sc/source/core/tool/formulagroup.cxx +++ b/sc/source/core/tool/formulagroup.cxx @@ -29,6 +29,23 @@ namespace sc { +rtl_uString* FormulaGroupContext::intern( const OUString& rStr ) +{ + StrHashType::iterator it = maStrPool.find(rStr); + if (it == maStrPool.end()) + { + // Not yet in the pool. + std::pair<StrHashType::iterator, bool> r = maStrPool.insert(rStr.intern()); + if (!r.second) + // Insertion failed. + return NULL; + + it = r.first; + } + + return it->pData; +} + namespace { /** @@ -63,7 +80,49 @@ void fillMatrix( ScMatrix& rMat, size_t nCol, const double* pNums, size_t nLen ) { // Flush last non-NaN segment to the matrix. rMat.PutDouble(pHead, p - pHead, nCol, pHead - pNums); - pHead = NULL; + } +} + +void fillMatrix( ScMatrix& rMat, size_t nCol, rtl_uString** pStrs, size_t nLen ) +{ + rtl_uString** p = pStrs; + rtl_uString** pEnd = p + nLen; + rtl_uString** pHead = NULL; + for (; p != pEnd; ++p) + { + if (*p) + { + if (!pHead) + // Store the first non-empty string position. + pHead = p; + + continue; + } + + if (pHead) + { + // Flush this non-empty segment to the matrix. + size_t nOffset = pHead - pStrs; + std::vector<OUString> aStrs; + aStrs.reserve(p - pHead); + for (; pHead != p; ++pHead) + aStrs.push_back(OUString(*pHead)); + + rMat.PutString(&aStrs[0], aStrs.size(), nCol, nOffset); + pHead = NULL; + } + } + + if (pHead) + { + // Flush last non-empty segment to the matrix. + size_t nOffset = pHead - pStrs; + std::vector<OUString> aStrs; + aStrs.reserve(p - pHead); + for (; pHead != p; ++pHead) + aStrs.push_back(OUString(*pHead)); + + rMat.PutString(&aStrs[0], aStrs.size(), nCol, nOffset); } } @@ -124,7 +183,14 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres aCode2.AddDouble(fVal); } else - aCode2.AddString(static_cast<size_t>(i) < p2->GetArrayLength() ? rArray.mpStringArray[i] : OUString()); + { + rtl_uString* pStr = NULL; + if (static_cast<size_t>(i) < p2->GetArrayLength()) + pStr = rArray.mpStringArray[i]; + + if (pStr) + aCode2.AddString(OUString(pStr)); + } } break; case formula::svDoubleVectorRef: @@ -138,6 +204,10 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres nRowEnd += i; size_t nRowSize = nRowEnd - nRowStart + 1; ScMatrixRef pMat(new ScMatrix(nColSize, nRowSize)); + if (p2->GetArrayLength() < nRowSize) + // Data array is shorter than the row size of the reference. Truncate it. + nRowSize = p2->GetArrayLength(); + for (size_t nCol = 0; nCol < nColSize; ++nCol) { const formula::VectorRefArray& rArray = rArrays[nCol]; @@ -149,9 +219,9 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres } else { - const OUString* pStrs = rArray.mpStringArray; + rtl_uString** pStrs = rArray.mpStringArray; pStrs += nRowStart; - pMat->PutString(pStrs, nRowSize, nCol, 0); + fillMatrix(*pMat, nCol, pStrs, nRowSize); } } commit 6dd0d051e986b868bf2225c16137e72d6e2dd3b6 Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Sep 9 15:32:25 2013 -0400 Do the same for range vector tokens. Change-Id: Id80f76dbe575fc6b279dafbfc524a9230755ddc8 diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 5f7f843..34ecbb2 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -2268,8 +2268,10 @@ formula::VectorRefArray ScColumn::FetchVectorRefArray( sc::FormulaGroupContext& { if (nLenRequested <= nLen) { - // Fill the whole length with zero. - rCxt.maNumArrays.push_back(new sc::FormulaGroupContext::NumArrayType(nLenRequested, 0.0)); + // Fill the whole length with NaN's. + double fNan; + rtl::math::setNan(&fNan); + rCxt.maNumArrays.push_back(new sc::FormulaGroupContext::NumArrayType(nLenRequested, fNan)); return formula::VectorRefArray(&rCxt.maNumArrays.back()[0]); } diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx index ca888dc..f6a1dff 100644 --- a/sc/source/core/tool/formulagroup.cxx +++ b/sc/source/core/tool/formulagroup.cxx @@ -29,6 +29,46 @@ namespace sc { +namespace { + +/** + * Input double array consists of segments of NaN's and normal values. + * Insert only the normal values into the matrix while skipping the NaN's. + */ +void fillMatrix( ScMatrix& rMat, size_t nCol, const double* pNums, size_t nLen ) +{ + const double* p = pNums; + const double* pEnd = p + nLen; + const double* pHead = NULL; + for (; p != pEnd; ++p) + { + if (!rtl::math::isNan(*p)) + { + if (!pHead) + // Store the first non-NaN position. + pHead = p; + + continue; + } + + if (pHead) + { + // Flush this non-NaN segment to the matrix. + rMat.PutDouble(pHead, p - pHead, nCol, pHead - pNums); + pHead = NULL; + } + } + + if (pHead) + { + // Flush last non-NaN segment to the matrix. + rMat.PutDouble(pHead, p - pHead, nCol, pHead - pNums); + pHead = NULL; + } +} + +} + ScMatrixRef FormulaGroupInterpreterSoftware::inverseMatrix(const ScMatrix& /*rMat*/) { return ScMatrixRef(); @@ -97,7 +137,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres if (!p2->IsEndFixed()) nRowEnd += i; size_t nRowSize = nRowEnd - nRowStart + 1; - ScMatrixRef pMat(new ScMatrix(nColSize, nRowSize, 0.0)); + ScMatrixRef pMat(new ScMatrix(nColSize, nRowSize)); for (size_t nCol = 0; nCol < nColSize; ++nCol) { const formula::VectorRefArray& rArray = rArrays[nCol]; @@ -105,7 +145,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres { const double* pNums = rArray.mpNumericArray; pNums += nRowStart; - pMat->PutDouble(pNums, nRowSize, nCol, 0); + fillMatrix(*pMat, nCol, pNums, nRowSize); } else { commit d1c90e929ef765b0d88a8d1e0bda434a1e340bee Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Sep 9 14:24:10 2013 -0400 Correctly handle empty cells in group calculation (software interpreter). Store NaN's to represent empty cells rather than storing 0's. Storing 0's would mess up COUNT(), for example. Change-Id: I8e350e1fe31358b844dd44451ed8659172fda1cb diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 9d0130c..5f7f843 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -2055,6 +2055,9 @@ bool appendDouble( sc::CellStoreType::iterator it, const sc::CellStoreType::iterator& itEnd ) { size_t nLenRemain = nLen; + double fNan; + rtl::math::setNan(&fNan); + for (; it != itEnd; ++it) { switch (it->type) @@ -2119,15 +2122,15 @@ bool appendDouble( break; case sc::element_type_empty: { - // Fill it with 0's. + // Fill it with NaN's. if (nLenRemain >= it->size) { - rArray.resize(rArray.size() + it->size, 0); + rArray.resize(rArray.size() + it->size, fNan); nLenRemain -= it->size; } else { - rArray.resize(rArray.size() + nLenRemain, 0); + rArray.resize(rArray.size() + nLenRemain, fNan); nLenRemain = 0; } } diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx index 6c930e5..ca888dc 100644 --- a/sc/source/core/tool/formulagroup.cxx +++ b/sc/source/core/tool/formulagroup.cxx @@ -50,6 +50,9 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres aResults.reserve(xGroup->mnLength); CachedTokensType aCachedTokens; + double fNan; + rtl::math::setNan(&fNan); + for (SCROW i = 0; i < xGroup->mnLength; ++i, aTmpPos.IncRow()) { ScTokenArray aCode2; @@ -70,7 +73,16 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres const formula::SingleVectorRefToken* p2 = static_cast<const formula::SingleVectorRefToken*>(p); const formula::VectorRefArray& rArray = p2->GetArray(); if (rArray.mbNumeric) - aCode2.AddDouble(static_cast<size_t>(i) < p2->GetArrayLength() ? rArray.mpNumericArray[i] : 0.0); + { + double fVal = fNan; + if (static_cast<size_t>(i) < p2->GetArrayLength()) + fVal = rArray.mpNumericArray[i]; + + if (rtl::math::isNan(fVal)) + aCode2.AddToken(ScEmptyCellToken(false, false)); + else + aCode2.AddDouble(fVal); + } else aCode2.AddString(static_cast<size_t>(i) < p2->GetArrayLength() ? rArray.mpStringArray[i] : OUString()); } diff --git a/sc/source/core/tool/interpr6.cxx b/sc/source/core/tool/interpr6.cxx index 4dbbf1d..470c8d8 100644 --- a/sc/source/core/tool/interpr6.cxx +++ b/sc/source/core/tool/interpr6.cxx @@ -880,7 +880,7 @@ void ScInterpreter::ScCount() while (nParamCount-- > 0) { - switch (GetStackType()) + switch (GetRawStackType()) { case svString: { commit 2e5111f58994d6449fd03b1fc2c4971da78deded Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Sep 9 11:05:03 2013 -0400 The OpenCL interpreter doesn't have to be a child class of the S/W one. Change-Id: Idcc28b98fceaffdc8947410fef5fadbae462450b diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx index 0f8b46f..279ac2d 100644 --- a/sc/source/core/opencl/formulagroupcl.cxx +++ b/sc/source/core/opencl/formulagroupcl.cxx @@ -104,7 +104,7 @@ public: }; -class FormulaGroupInterpreterOpenCL : public FormulaGroupInterpreterSoftware +class FormulaGroupInterpreterOpenCL : public FormulaGroupInterpreter { SourceData *mSrcDataStack[SRCDATASIZE]; unsigned int mnStackPointer,mnDoublePtrCount; @@ -124,7 +124,7 @@ class FormulaGroupInterpreterOpenCL : public FormulaGroupInterpreterSoftware size_t mnRowSize; public: FormulaGroupInterpreterOpenCL() : - FormulaGroupInterpreterSoftware() + FormulaGroupInterpreter() { mnStackPointer = 0; mnpOclEndPos = NULL; @@ -952,6 +952,9 @@ bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc, const ScAddress /// Special case of formula compiler for groundwatering class FormulaGroupInterpreterGroundwater : public FormulaGroupInterpreterSoftware { + bool interpretCL(ScDocument& rDoc, const ScAddress& rTopPos, + const ScFormulaCellGroupRef& xGroup, ScTokenArray& rCode); + public: FormulaGroupInterpreterGroundwater() : FormulaGroupInterpreterSoftware() @@ -965,8 +968,6 @@ public: } virtual ScMatrixRef inverseMatrix(const ScMatrix& /* rMat */) { return ScMatrixRef(); } - virtual bool interpretCL(ScDocument& rDoc, const ScAddress& rTopPos, - const ScFormulaCellGroupRef& xGroup, ScTokenArray& rCode); virtual bool interpret(ScDocument& rDoc, const ScAddress& rTopPos, const ScFormulaCellGroupRef& xGroup, ScTokenArray& rCode); }; commit f4d04f2014cedacdba3eec2177a3ba4acd3d6b6f Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Sep 9 10:52:42 2013 -0400 Instantiate the software fallback outside of opencl code. Change-Id: I7ec7a951492616abd3c7327b85f09c1e913208ca diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx index 0ae58e8..0f8b46f 100644 --- a/sc/source/core/opencl/formulagroupcl.cxx +++ b/sc/source/core/opencl/formulagroupcl.cxx @@ -1063,18 +1063,18 @@ bool FormulaGroupInterpreterGroundwater::interpret(ScDocument& rDoc, const ScAdd } namespace opencl { - sc::FormulaGroupInterpreter *createFormulaGroupInterpreter() - { - if (getenv("SC_SOFTWARE")) - { - fprintf(stderr, "Create S/W interp\n"); - return new sc::FormulaGroupInterpreterSoftware(); - } - if (getenv("SC_GROUNDWATER")) - return new sc::FormulaGroupInterpreterGroundwater(); - else - return new sc::FormulaGroupInterpreterOpenCL(); - } + +sc::FormulaGroupInterpreter *createFormulaGroupInterpreter() +{ + if (getenv("SC_SOFTWARE")) + return NULL; + + if (getenv("SC_GROUNDWATER")) + return new sc::FormulaGroupInterpreterGroundwater(); + + return new sc::FormulaGroupInterpreterOpenCL(); +} + } // namespace opencl } // namespace sc diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx index 2ea09c4..6c930e5 100644 --- a/sc/source/core/tool/formulagroup.cxx +++ b/sc/source/core/tool/formulagroup.cxx @@ -216,7 +216,10 @@ FormulaGroupInterpreter *FormulaGroupInterpreter::getStatic() msInstance = sc::opencl::createFormulaGroupInterpreter(); #endif if ( !msInstance ) // software fallback + { + fprintf(stderr, "Create S/W interp\n"); msInstance = new sc::FormulaGroupInterpreterSoftware(); + } } return msInstance; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits