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);

Reply via email to