[Libreoffice-commits] .: Branch 'feature/matrix-new-backend' - 2 commits - sc/inc sc/source

Kohei Yoshida kohei at kemper.freedesktop.org
Wed Jul 18 12:07:15 PDT 2012


 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.yoshida at 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.yoshida at 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;
 }
 


More information about the Libreoffice-commits mailing list