sc/inc/scmatrix.hxx | 2 sc/source/core/tool/interpr1.cxx | 59 ----------------------- sc/source/core/tool/scmatrix.cxx | 97 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 58 deletions(-)
New commits: commit f91611df0c818116cf8d62569dd83ea9c02ea41c Author: Noel Grandin <noelgran...@gmail.com> AuthorDate: Wed Apr 16 19:59:50 2025 +0200 Commit: Noel Grandin <noelgran...@gmail.com> CommitDate: Fri Apr 18 18:21:46 2025 +0200 tdf#163872 speed up IfJump operation shaves 10% off the load time here by moving the loop of the operation down into the matrix code where we can iterate direcltly over the data. Change-Id: I88f66d0ab3c7fc9e09ccffb96c0fd335daf62169 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184343 Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> Tested-by: Jenkins diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx index 2b0a6e64c32a..31428042a17f 100644 --- a/sc/inc/scmatrix.hxx +++ b/sc/inc/scmatrix.hxx @@ -37,6 +37,7 @@ class ScInterpreter; struct ScInterpreterContext; class ScMatrixImpl; enum class FormulaError : sal_uInt16; +class ScJumpMatrix; namespace sc { @@ -378,6 +379,7 @@ public: size_t Count(bool bCountStrings, bool bCountErrors, bool bIgnoreEmptyStrings = false) const ; size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const ; size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const ; + void IfJump( ScJumpMatrix& rJumpMatrix, const short* pJump, short nJumpCount ) const ; double GetMaxValue( bool bTextAsZero, bool bIgnoreErrorValues = false ) const ; double GetMinValue( bool bTextAsZero, bool bIgnoreErrorValues = false ) const ; diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 4d25848c590d..63aa0583e4a3 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -121,64 +121,7 @@ void ScInterpreter::ScIfJump() { std::shared_ptr<ScJumpMatrix> pJumpMat( std::make_shared<ScJumpMatrix>( pCur->GetOpCode(), nCols, nRows)); - for ( SCSIZE nC=0; nC < nCols; ++nC ) - { - for ( SCSIZE nR=0; nR < nRows; ++nR ) - { - double fVal; - bool bTrue; - bool bIsValue = pMat->IsValue(nC, nR); - if (bIsValue) - { - fVal = pMat->GetDouble(nC, nR); - bIsValue = std::isfinite(fVal); - bTrue = bIsValue && (fVal != 0.0); - if (bTrue) - fVal = 1.0; - } - else - { - // Treat empty and empty path as 0, but string - // as error. ScMatrix::IsValueOrEmpty() returns - // true for any empty, empty path, empty cell, - // empty result. - bIsValue = pMat->IsValueOrEmpty(nC, nR); - bTrue = false; - fVal = (bIsValue ? 0.0 : CreateDoubleError( FormulaError::NoValue)); - } - if ( bTrue ) - { // TRUE - if( nJumpCount >= 2 ) - { // THEN path - pJumpMat->SetJump( nC, nR, fVal, - pJump[ 1 ], - pJump[ nJumpCount ]); - } - else - { // no parameter given for THEN - pJumpMat->SetJump( nC, nR, fVal, - pJump[ nJumpCount ], - pJump[ nJumpCount ]); - } - } - else - { // FALSE - if( nJumpCount == 3 && bIsValue ) - { // ELSE path - pJumpMat->SetJump( nC, nR, fVal, - pJump[ 2 ], - pJump[ nJumpCount ]); - } - else - { // no parameter given for ELSE, - // or DoubleError - pJumpMat->SetJump( nC, nR, fVal, - pJump[ nJumpCount ], - pJump[ nJumpCount ]); - } - } - } - } + pMat->IfJump(*pJumpMat, pJump, nJumpCount); xNew = new ScJumpMatrixToken(std::move(pJumpMat)); GetTokenMatrixMap().emplace(pCur, xNew); } diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx index 6ec0f437ac79..a8f27380d9aa 100644 --- a/sc/source/core/tool/scmatrix.cxx +++ b/sc/source/core/tool/scmatrix.cxx @@ -26,6 +26,7 @@ #include <compare.hxx> #include <matrixoperators.hxx> #include <math.hxx> +#include <jumpmatrix.hxx> #include <svl/numformat.hxx> #include <svl/zforlist.hxx> @@ -318,6 +319,7 @@ public: size_t Count(bool bCountStrings, bool bCountErrors, bool bIgnoreEmptyStrings) const; size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const; size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const; + void IfJump( ScJumpMatrix& rJumpMatrix, const short* pJump, short nJumpCount ) const ; double GetMaxValue( bool bTextAsZero, bool bIgnoreErrorValues ) const; double GetMinValue( bool bTextAsZero, bool bIgnoreErrorValues ) const; @@ -2172,6 +2174,96 @@ size_t ScMatrixImpl::MatchStringInColumns(const svl::SharedString& rStr, size_t return aFunc.getMatching(); } +void ScMatrixImpl::IfJump( ScJumpMatrix& rJumpMatrix, const short* pJump, short nJumpCount ) const +{ + const MatrixImplType::size_pair_type aSize = maMat.size(); + const SCSIZE nRows = aSize.row; + const SCSIZE nCols = aSize.column; + MatrixImplType::const_position_type aPos = maMat.position(0, 0); + for (SCSIZE nC = 0; nC < nCols; ++nC) + { + for (SCSIZE nR = 0; nR < nRows; ++nR) + { + bool bIsValue; + bool bTrue; + double fVal; + mdds::mtm::element_t eType = maMat.get_type(aPos); + switch (eType) + { + case mdds::mtm::element_boolean: + fVal = maMat.get_boolean(aPos) ? 1.0 : 0.0; + bIsValue = std::isfinite(fVal); + bTrue = bIsValue && (fVal != 0.0); + if (bTrue) + fVal = 1.0; + break; + case mdds::mtm::element_numeric: + fVal = maMat.get_numeric(aPos); + bIsValue = std::isfinite(fVal); + bTrue = bIsValue && (fVal != 0.0); + if (bTrue) + fVal = 1.0; + break; + case mdds::mtm::element_string: + // Treat empty and empty path as 0, but string + // as error. ScMatrix::IsValueOrEmpty() returns + // true for any empty, empty path, empty cell, + // empty result. + bIsValue = false; + bTrue = false; + fVal = (bIsValue ? 0.0 : CreateDoubleError( FormulaError::NoValue)); + break; + case mdds::mtm::element_empty: + // Treat empty and empty path as 0, but string + // as error. ScMatrix::IsValueOrEmpty() returns + // true for any empty, empty path, empty cell, + // empty result. + bIsValue = true; + bTrue = false; + fVal = (bIsValue ? 0.0 : CreateDoubleError( FormulaError::NoValue)); + break; + default: + assert(false); + bIsValue = true; + bTrue = false; + fVal = 0; + } + if ( bTrue ) + { // TRUE + if( nJumpCount >= 2 ) + { // THEN path + rJumpMatrix.SetJump( nC, nR, fVal, + pJump[ 1 ], + pJump[ nJumpCount ]); + } + else + { // no parameter given for THEN + rJumpMatrix.SetJump( nC, nR, fVal, + pJump[ nJumpCount ], + pJump[ nJumpCount ]); + } + } + else + { // FALSE + if( nJumpCount == 3 && bIsValue ) + { // ELSE path + rJumpMatrix.SetJump( nC, nR, fVal, + pJump[ 2 ], + pJump[ nJumpCount ]); + } + else + { // no parameter given for ELSE, + // or DoubleError + rJumpMatrix.SetJump( nC, nR, fVal, + pJump[ nJumpCount ], + pJump[ nJumpCount ]); + } + } + aPos = MatrixImplType::next_position(aPos); + } + } +} + double ScMatrixImpl::GetMaxValue( bool bTextAsZero, bool bIgnoreErrorValues ) const { CalcMaxMinValue<MaxOp> aFunc(bTextAsZero, bIgnoreErrorValues); @@ -3481,6 +3573,11 @@ ScMatrix::KahanIterateResult ScMatrix::SumSquare(bool bTextAsZero, bool bIgnoreE return pImpl->SumSquare(bTextAsZero, bIgnoreErrorValues); } +void ScMatrix::IfJump(ScJumpMatrix& rJumpMatrix, const short* pJump, short nJumpCount) const +{ + return pImpl->IfJump(rJumpMatrix, pJump, nJumpCount); +} + ScMatrix::DoubleIterateResult ScMatrix::Product(bool bTextAsZero, bool bIgnoreErrorValues) const { return pImpl->Product(bTextAsZero, bIgnoreErrorValues);