sc/inc/scmatrix.hxx | 5 sc/source/core/tool/interpr5.cxx | 202 +++++++++++++++++++++++++++------------ sc/source/core/tool/scmatrix.cxx | 36 ++++++ 3 files changed, 183 insertions(+), 60 deletions(-)
New commits: commit 9d96705b9a035944d0a3f53d8d56633458e7883c Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Wed Jul 18 15:06:45 2012 -0400 Pass contiguous cell data as an array to matrix. This is faster. It's generally faster to pass an array of elements to matrix than passing them individually. Change-Id: I4502025d08040327c1d1c09ce1756928be054c25 diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx index 034bc4d..b40ba08 100644 --- a/sc/inc/scmatrix.hxx +++ b/sc/inc/scmatrix.hxx @@ -261,9 +261,14 @@ public: void PutDouble( double fVal, SCSIZE nC, SCSIZE nR); void PutDouble( double fVal, SCSIZE nIndex); + void PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR); + void PutString( const ::rtl::OUString& rStr, SCSIZE nC, SCSIZE nR); void PutString( const ::rtl::OUString& rStr, SCSIZE nIndex); + void PutString(const rtl::OUString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR); + void PutEmpty( SCSIZE nC, SCSIZE nR); + /// Jump FALSE without path void PutEmptyPath( SCSIZE nC, SCSIZE nR); void PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR ); diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx index fb1a496..20c83f3 100644 --- a/sc/source/core/tool/interpr5.cxx +++ b/sc/source/core/tool/interpr5.cxx @@ -351,6 +351,43 @@ ScInterpreter::VolatileType ScInterpreter::GetVolatileType() const return meVolatileType; } +namespace { + +struct CellBucket +{ + SCSIZE mnNumValStart; + SCSIZE mnStrValStart; + std::vector<double> maNumVals; + std::vector<rtl::OUString> maStrVals; + + CellBucket() : mnNumValStart(0), mnStrValStart(0) {} + + void flush(ScMatrix& rMat, SCSIZE nCol) + { + if (!maNumVals.empty()) + { + const double* p = &maNumVals[0]; + rMat.PutDouble(p, maNumVals.size(), nCol, mnNumValStart); + reset(); + } + else if (!maStrVals.empty()) + { + const rtl::OUString* p = &maStrVals[0]; + rMat.PutString(p, maStrVals.size(), nCol, mnStrValStart); + reset(); + } + } + + void reset() + { + mnNumValStart = mnStrValStart = 0; + maNumVals.clear(); + maStrVals.clear(); + } +}; + +} + ScMatrixRef ScInterpreter::CreateMatrixFromDoubleRef( const FormulaToken* pToken, SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2 ) @@ -382,46 +419,89 @@ ScMatrixRef ScInterpreter::CreateMatrixFromDoubleRef( const FormulaToken* pToken if (!pMat || nGlobalError) return NULL; - ScCellIterator aCellIter( - pDok, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); + CellBucket aBucket; - for (ScBaseCell* pCell = aCellIter.GetFirst(); pCell; pCell = - aCellIter.GetNext()) + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) { - SCCOL nThisCol = aCellIter.GetCol(); - SCROW nThisRow = aCellIter.GetRow(); - if (HasCellEmptyData(pCell)) - continue; + // Scan one column at a time, to pass a sequence of values to matrix in one call. + ScCellIterator aCellIter( + pDok, nCol, nRow1, nTab1, nCol, nRow2, nTab2); + + SCROW nPrevRow = -2, nThisRow = -2; - if (HasCellValueData(pCell)) + for (ScBaseCell* pCell = aCellIter.GetFirst(); pCell; pCell = aCellIter.GetNext(), nPrevRow = nThisRow) { - ScAddress aAdr( nThisCol, nThisRow, nTab1); - double fVal = GetCellValue( aAdr, pCell); + nThisRow = aCellIter.GetRow(); + + if (HasCellEmptyData(pCell)) + { + aBucket.flush(*pMat, static_cast<SCSIZE>(nCol-nCol1)); + continue; + } + + if (HasCellValueData(pCell)) + { + ScAddress aAdr(nCol, nThisRow, nTab1); + double fVal = GetCellValue( aAdr, pCell); + if ( nGlobalError ) + { + fVal = CreateDoubleError( nGlobalError); + nGlobalError = 0; + } + + if (nThisRow == nPrevRow + 1) + { + // Secondary numbers. + aBucket.maNumVals.push_back(fVal); + } + else + { + // First number. + aBucket.flush(*pMat, static_cast<SCSIZE>(nCol-nCol1)); + aBucket.mnNumValStart = nThisRow - nRow1; + aBucket.maNumVals.push_back(fVal); + } + continue; + } + + String aStr; + GetCellString( aStr, pCell); if ( nGlobalError ) { - fVal = CreateDoubleError( nGlobalError); + double fVal = CreateDoubleError( nGlobalError); nGlobalError = 0; + + if (nThisRow == nPrevRow + 1) + { + // Secondary numbers. + aBucket.maNumVals.push_back(fVal); + } + else + { + // First number. + aBucket.flush(*pMat, static_cast<SCSIZE>(nCol-nCol1)); + aBucket.mnNumValStart = nThisRow - nRow1; + aBucket.maNumVals.push_back(fVal); + } + } + else + { + if (nThisRow == nPrevRow + 1) + { + // Secondary numbers. + aBucket.maStrVals.push_back(aStr); + } + else + { + // First number. + aBucket.flush(*pMat, static_cast<SCSIZE>(nCol-nCol1)); + aBucket.mnStrValStart = nThisRow - nRow1; + aBucket.maStrVals.push_back(aStr); + } } - pMat->PutDouble( fVal, - static_cast<SCSIZE>(nThisCol-nCol1), - static_cast<SCSIZE>(nThisRow-nRow1)); - continue; } - String aStr; - GetCellString( aStr, pCell); - if ( nGlobalError ) - { - double fVal = CreateDoubleError( nGlobalError); - nGlobalError = 0; - pMat->PutDouble( fVal, - static_cast<SCSIZE>(nThisCol-nCol1), - static_cast<SCSIZE>(nThisRow-nRow1)); - } - else - pMat->PutString( aStr, - static_cast<SCSIZE>(nThisCol-nCol1), - static_cast<SCSIZE>(nThisRow-nRow1)); + aBucket.flush(*pMat, static_cast<SCSIZE>(nCol-nCol1)); } if (pTokenMatrixMap) diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx index 8ff39c6..0a5f680 100644 --- a/sc/source/core/tool/scmatrix.cxx +++ b/sc/source/core/tool/scmatrix.cxx @@ -343,10 +343,14 @@ public: bool ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const; bool ValidColRowOrReplicated( SCSIZE & rC, SCSIZE & rR ) const; void SetErrorAtInterpreter( sal_uInt16 nError ) const; + void PutDouble(double fVal, SCSIZE nC, SCSIZE nR); void PutDouble( double fVal, SCSIZE nIndex); + void PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR); + void PutString(const ::rtl::OUString& rStr, SCSIZE nC, SCSIZE nR); void PutString(const ::rtl::OUString& rStr, SCSIZE nIndex); + void PutString(const rtl::OUString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR); void PutEmpty(SCSIZE nC, SCSIZE nR); void PutEmptyPath(SCSIZE nC, SCSIZE nR); @@ -495,6 +499,16 @@ void ScMatrixImpl::PutDouble(double fVal, SCSIZE nC, SCSIZE nR) } } +void ScMatrixImpl::PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) +{ + if (ValidColRow( nC, nR)) + maMat.set(nR, nC, pArray, pArray + nLen); + else + { + OSL_FAIL("ScMatrixImpl::PutDouble: dimension error"); + } +} + void ScMatrixImpl::PutDouble( double fVal, SCSIZE nIndex) { SCSIZE nC, nR; @@ -505,7 +519,17 @@ void ScMatrixImpl::PutDouble( double fVal, SCSIZE nIndex) void ScMatrixImpl::PutString(const ::rtl::OUString& rStr, SCSIZE nC, SCSIZE nR) { if (ValidColRow( nC, nR)) - maMat.set(nR, nC, rtl::OUString(rStr)); + maMat.set(nR, nC, rStr); + else + { + OSL_FAIL("ScMatrixImpl::PutString: dimension error"); + } +} + +void ScMatrixImpl::PutString(const rtl::OUString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) +{ + if (ValidColRow( nC, nR)) + maMat.set(nR, nC, pArray, pArray + nLen); else { OSL_FAIL("ScMatrixImpl::PutString: dimension error"); @@ -1181,6 +1205,11 @@ void ScMatrix::PutDouble( double fVal, SCSIZE nIndex) pImpl->PutDouble(fVal, nIndex); } +void ScMatrix::PutDouble(const double* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) +{ + pImpl->PutDouble(pArray, nLen, nC, nR); +} + void ScMatrix::PutString(const ::rtl::OUString& rStr, SCSIZE nC, SCSIZE nR) { pImpl->PutString(rStr, nC, nR); @@ -1191,6 +1220,11 @@ void ScMatrix::PutString(const ::rtl::OUString& rStr, SCSIZE nIndex) pImpl->PutString(rStr, nIndex); } +void ScMatrix::PutString(const rtl::OUString* pArray, size_t nLen, SCSIZE nC, SCSIZE nR) +{ + pImpl->PutString(pArray, nLen, nC, nR); +} + void ScMatrix::PutEmpty(SCSIZE nC, SCSIZE nR) { pImpl->PutEmpty(nC, nR); commit 8c4f226bd888e7af6784324e974764c562ed88a4 Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Wed Jul 18 11:29:12 2012 -0400 Less indentations via early bailout. Change-Id: Iae2b91fc732debe9b5c9cdd7c4717e1ef2fac08e diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx index c689729..fb1a496 100644 --- a/sc/source/core/tool/interpr5.cxx +++ b/sc/source/core/tool/interpr5.cxx @@ -355,75 +355,79 @@ ScMatrixRef ScInterpreter::CreateMatrixFromDoubleRef( const FormulaToken* pToken SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2 ) { - RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CreateMatrixFromDoubleRef" ); - ScMatrixRef pMat = NULL; - if (nTab1 == nTab2 && !nGlobalError) - { - ScTokenMatrixMap::const_iterator aIter; - if ( static_cast<SCSIZE>(nRow2 - nRow1 + 1) * - static_cast<SCSIZE>(nCol2 - nCol1 + 1) > - ScMatrix::GetElementsMax() ) - SetError(errStackOverflow); - else if (pTokenMatrixMap && ((aIter = pTokenMatrixMap->find( pToken)) - != pTokenMatrixMap->end())) - pMat = static_cast<ScToken*>((*aIter).second.get())->GetMatrix(); - else - { - SCSIZE nMatCols = static_cast<SCSIZE>(nCol2 - nCol1 + 1); - SCSIZE nMatRows = static_cast<SCSIZE>(nRow2 - nRow1 + 1); - pMat = GetNewMat( nMatCols, nMatRows, true); - if (pMat && !nGlobalError) - { - ScCellIterator aCellIter( - pDok, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); + if (nTab1 != nTab2 || nGlobalError) + { + // Not a 2D matrix. + SetError(errIllegalParameter); + return NULL; + } - for (ScBaseCell* pCell = aCellIter.GetFirst(); pCell; pCell = - aCellIter.GetNext()) - { - SCCOL nThisCol = aCellIter.GetCol(); - SCROW nThisRow = aCellIter.GetRow(); - if (HasCellEmptyData(pCell)) - continue; + SCSIZE nMatCols = static_cast<SCSIZE>(nCol2 - nCol1 + 1); + SCSIZE nMatRows = static_cast<SCSIZE>(nRow2 - nRow1 + 1); - if (HasCellValueData(pCell)) - { - ScAddress aAdr( nThisCol, nThisRow, nTab1); - double fVal = GetCellValue( aAdr, pCell); - if ( nGlobalError ) - { - fVal = CreateDoubleError( nGlobalError); - nGlobalError = 0; - } - pMat->PutDouble( fVal, - static_cast<SCSIZE>(nThisCol-nCol1), - static_cast<SCSIZE>(nThisRow-nRow1)); - continue; - } + if (nMatRows * nMatCols > ScMatrix::GetElementsMax()) + { + SetError(errStackOverflow); + return NULL; + } - String aStr; - GetCellString( aStr, pCell); - if ( nGlobalError ) - { - double fVal = CreateDoubleError( nGlobalError); - nGlobalError = 0; - pMat->PutDouble( fVal, - static_cast<SCSIZE>(nThisCol-nCol1), - static_cast<SCSIZE>(nThisRow-nRow1)); - } - else - pMat->PutString( aStr, - static_cast<SCSIZE>(nThisCol-nCol1), - static_cast<SCSIZE>(nThisRow-nRow1)); - } + ScTokenMatrixMap::const_iterator aIter; + if (pTokenMatrixMap && ((aIter = pTokenMatrixMap->find( pToken)) + != pTokenMatrixMap->end())) + { + return static_cast<ScToken*>((*aIter).second.get())->GetMatrix(); + } + + ScMatrixRef pMat = GetNewMat( nMatCols, nMatRows, true); + if (!pMat || nGlobalError) + return NULL; - if (pTokenMatrixMap) - pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( - pToken, new ScMatrixToken( pMat))); + ScCellIterator aCellIter( + pDok, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); + + for (ScBaseCell* pCell = aCellIter.GetFirst(); pCell; pCell = + aCellIter.GetNext()) + { + SCCOL nThisCol = aCellIter.GetCol(); + SCROW nThisRow = aCellIter.GetRow(); + if (HasCellEmptyData(pCell)) + continue; + + if (HasCellValueData(pCell)) + { + ScAddress aAdr( nThisCol, nThisRow, nTab1); + double fVal = GetCellValue( aAdr, pCell); + if ( nGlobalError ) + { + fVal = CreateDoubleError( nGlobalError); + nGlobalError = 0; } + pMat->PutDouble( fVal, + static_cast<SCSIZE>(nThisCol-nCol1), + static_cast<SCSIZE>(nThisRow-nRow1)); + continue; + } + + String aStr; + GetCellString( aStr, pCell); + if ( nGlobalError ) + { + double fVal = CreateDoubleError( nGlobalError); + nGlobalError = 0; + pMat->PutDouble( fVal, + static_cast<SCSIZE>(nThisCol-nCol1), + static_cast<SCSIZE>(nThisRow-nRow1)); } + else + pMat->PutString( aStr, + static_cast<SCSIZE>(nThisCol-nCol1), + static_cast<SCSIZE>(nThisRow-nRow1)); } - else // not a 2D matrix - SetError(errIllegalParameter); + + if (pTokenMatrixMap) + pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( + pToken, new ScMatrixToken( pMat))); + return pMat; } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits