[Libreoffice-commits] .: 22 commits - mdds/prj sc/inc sc/qa sc/source

Kohei Yoshida kohei at kemper.freedesktop.org
Thu Jul 19 11:22:49 PDT 2012


 mdds/prj/d.lst                              |    3 
 sc/inc/scmatrix.hxx                         |   68 +-
 sc/qa/unit/ucalc.cxx                        |  113 +---
 sc/source/core/data/cell.cxx                |    8 
 sc/source/core/data/validat.cxx             |    2 
 sc/source/core/inc/interpre.hxx             |    2 
 sc/source/core/inc/jumpmatrix.hxx           |    2 
 sc/source/core/tool/addincol.cxx            |    6 
 sc/source/core/tool/ddelink.cxx             |    2 
 sc/source/core/tool/interpr1.cxx            |    8 
 sc/source/core/tool/interpr5.cxx            |  372 ++++++++------
 sc/source/core/tool/rangeseq.cxx            |    2 
 sc/source/core/tool/scmatrix.cxx            |  695 ++++++++++++++++++----------
 sc/source/core/tool/token.cxx               |    2 
 sc/source/filter/excel/xihelper.cxx         |    2 
 sc/source/filter/xml/XMLDDELinksContext.cxx |    2 
 sc/source/ui/docshell/externalrefmgr.cxx    |    9 
 17 files changed, 759 insertions(+), 539 deletions(-)

New commits:
commit 73b05f75ad2cb1c648ed1a4e29b28d6f53a798e4
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Jul 19 14:22:31 2012 -0400

    Deliver a missing header.
    
    Change-Id: Ia50e0aeecdbe364c8d0862906f8f7dd842ebd9c8

diff --git a/mdds/prj/d.lst b/mdds/prj/d.lst
index 62d44f3..dc5828b 100644
--- a/mdds/prj/d.lst
+++ b/mdds/prj/d.lst
@@ -1,7 +1,8 @@
 mkdir: %_DEST%\inc\mdds
+mkdir: %_DEST%\inc\mdds\compat
 mkdir: %_DEST%\inc\mdds\hash_container
 
 ..\%__SRC%\inc\mdds\* %_DEST%\inc\mdds
+..\%__SRC%\inc\mdds\compat\* %_DEST%\inc\mdds\compat
 ..\%__SRC%\inc\mdds\hash_container\* %_DEST%\inc\mdds\hash_container
 
-
commit ce8ecf1d343224a6db823860e4dcf46d2dfe5654
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Jul 18 17:35:18 2012 -0400

    Specify function object as template argument rather than local variable.
    
    Also, replace pointers with references while I'm at it.
    
    Change-Id: I7f238650e5b04fe5f691c1260621431c60ff1883

diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index b358231..227186b 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -50,47 +50,49 @@
 using ::std::vector;
 using namespace formula;
 
+namespace {
+
 const double fInvEpsilon = 1.0E-7;
 
-// -----------------------------------------------------------------------
-    struct MatrixAdd : public ::std::binary_function<double,double,double>
-    {
-        inline double operator() (const double& lhs, const double& rhs) const
-        {
-            return ::rtl::math::approxAdd( lhs,rhs);
-        }
-    };
-    struct MatrixSub : public ::std::binary_function<double,double,double>
+struct MatrixAdd : public ::std::binary_function<double,double,double>
+{
+    inline double operator() (const double& lhs, const double& rhs) const
     {
-        inline double operator() (const double& lhs, const double& rhs) const
-        {
-            return ::rtl::math::approxSub( lhs,rhs);
-        }
-    };
-    struct MatrixMul : public ::std::binary_function<double,double,double>
+        return ::rtl::math::approxAdd( lhs,rhs);
+    }
+};
+
+struct MatrixSub : public ::std::binary_function<double,double,double>
+{
+    inline double operator() (const double& lhs, const double& rhs) const
     {
-        inline double operator() (const double& lhs, const double& rhs) const
-        {
-            return lhs * rhs;
-        }
-    };
-    struct MatrixDiv : public ::std::binary_function<double,double,double>
+        return ::rtl::math::approxSub( lhs,rhs);
+    }
+};
+
+struct MatrixMul : public ::std::binary_function<double,double,double>
+{
+    inline double operator() (const double& lhs, const double& rhs) const
     {
-        inline double operator() (const double& lhs, const double& rhs) const
-        {
-            return ScInterpreter::div( lhs,rhs);
-        }
-    };
-    struct MatrixPow : public ::std::binary_function<double,double,double>
+        return lhs * rhs;
+    }
+};
+
+struct MatrixDiv : public ::std::binary_function<double,double,double>
+{
+    inline double operator() (const double& lhs, const double& rhs) const
     {
-        inline double operator() (const double& lhs, const double& rhs) const
-        {
-            return ::pow( lhs,rhs);
-        }
-    };
+        return ScInterpreter::div( lhs,rhs);
+    }
+};
 
-namespace
+struct MatrixPow : public ::std::binary_function<double,double,double>
 {
+    inline double operator() (const double& lhs, const double& rhs) const
+    {
+        return ::pow( lhs,rhs);
+    }
+};
 
 // Multiply n x m Mat A with m x l Mat B to n x l Mat R
 void lcl_MFastMult(ScMatrixRef pA, ScMatrixRef pB, ScMatrixRef pR,
@@ -1146,25 +1148,28 @@ inline SCSIZE lcl_GetMinExtent( SCSIZE n1, SCSIZE n2 )
 }
 
 template<class _Function>
-ScMatrixRef lcl_MatrixCalculation(const _Function& _pOperation,ScMatrix* pMat1, ScMatrix* pMat2,ScInterpreter* _pIterpreter)
+ScMatrixRef lcl_MatrixCalculation(
+   const ScMatrix& rMat1, const ScMatrix& rMat2, ScInterpreter* pInterpreter)
 {
+    static _Function Op;
+
     SCSIZE nC1, nC2, nMinC;
     SCSIZE nR1, nR2, nMinR;
     SCSIZE i, j;
-    pMat1->GetDimensions(nC1, nR1);
-    pMat2->GetDimensions(nC2, nR2);
+    rMat1.GetDimensions(nC1, nR1);
+    rMat2.GetDimensions(nC2, nR2);
     nMinC = lcl_GetMinExtent( nC1, nC2);
     nMinR = lcl_GetMinExtent( nR1, nR2);
-    ScMatrixRef xResMat = _pIterpreter->GetNewMat(nMinC, nMinR);
+    ScMatrixRef xResMat = pInterpreter->GetNewMat(nMinC, nMinR);
     if (xResMat)
     {
         for (i = 0; i < nMinC; i++)
         {
             for (j = 0; j < nMinR; j++)
             {
-                if (pMat1->IsValueOrEmpty(i,j) && pMat2->IsValueOrEmpty(i,j))
+                if (rMat1.IsValueOrEmpty(i,j) && rMat2.IsValueOrEmpty(i,j))
                 {
-                    double d = _pOperation(pMat1->GetDouble(i,j),pMat2->GetDouble(i,j));
+                    double d = Op(rMat1.GetDouble(i,j), rMat2.GetDouble(i,j));
                     xResMat->PutDouble( d, i, j);
                 }
                 else
@@ -1301,13 +1306,11 @@ void ScInterpreter::CalculateAddSub(bool _bSub)
         ScMatrixRef pResMat;
         if ( _bSub )
         {
-            MatrixSub aSub;
-            pResMat = lcl_MatrixCalculation(aSub ,pMat1.get(), pMat2.get(),this);
+            pResMat = lcl_MatrixCalculation<MatrixSub>(*pMat1, *pMat2, this);
         }
         else
         {
-            MatrixAdd aAdd;
-            pResMat = lcl_MatrixCalculation(aAdd ,pMat1.get(), pMat2.get(),this);
+            pResMat = lcl_MatrixCalculation<MatrixAdd>(*pMat1, *pMat2, this);
         }
 
         if (!pResMat)
@@ -1514,8 +1517,7 @@ void ScInterpreter::ScMul()
     }
     if (pMat1 && pMat2)
     {
-        MatrixMul aMul;
-        ScMatrixRef pResMat = lcl_MatrixCalculation(aMul,pMat1.get(), pMat2.get(),this);
+        ScMatrixRef pResMat = lcl_MatrixCalculation<MatrixMul>(*pMat1, *pMat2, this);
         if (!pResMat)
             PushNoValue();
         else
@@ -1589,8 +1591,7 @@ void ScInterpreter::ScDiv()
     }
     if (pMat1 && pMat2)
     {
-        MatrixDiv aDiv;
-        ScMatrixRef pResMat = lcl_MatrixCalculation(aDiv,pMat1.get(), pMat2.get(),this);
+        ScMatrixRef pResMat = lcl_MatrixCalculation<MatrixDiv>(*pMat1, *pMat2, this);
         if (!pResMat)
             PushNoValue();
         else
@@ -1671,8 +1672,7 @@ void ScInterpreter::ScPow()
         fVal1 = GetDouble();
     if (pMat1 && pMat2)
     {
-        MatrixPow aPow;
-        ScMatrixRef pResMat = lcl_MatrixCalculation(aPow,pMat1.get(), pMat2.get(),this);
+        ScMatrixRef pResMat = lcl_MatrixCalculation<MatrixPow>(*pMat1, *pMat2, this);
         if (!pResMat)
             PushNoValue();
         else
@@ -1743,7 +1743,6 @@ void ScInterpreter::ScSumProduct()
     SCSIZE nR, nR1;
     pMat2->GetDimensions(nC, nR);
     pMat = pMat2;
-    MatrixMul aMul;
     for (sal_uInt16 i = 1; i < nParamCount; i++)
     {
         pMat1 = GetMatrix();
@@ -1758,7 +1757,7 @@ void ScInterpreter::ScSumProduct()
             PushNoValue();
             return;
         }
-        ScMatrixRef pResMat = lcl_MatrixCalculation(aMul,pMat1.get(), pMat.get(),this);
+        ScMatrixRef pResMat = lcl_MatrixCalculation<MatrixMul>(*pMat1, *pMat, this);
         if (!pResMat)
         {
             PushNoValue();
@@ -1853,8 +1852,7 @@ void ScInterpreter::ScSumXMY2()
         PushNoValue();
         return;
     } // if (nC1 != nC2 || nR1 != nR2)
-    MatrixSub aSub;
-    ScMatrixRef pResMat = lcl_MatrixCalculation(aSub,pMat1.get(), pMat2.get(),this);
+    ScMatrixRef pResMat = lcl_MatrixCalculation<MatrixSub>(*pMat1, *pMat2, this);
     if (!pResMat)
     {
         PushNoValue();
commit 4c1d32263e580d41e4b8fea58aab6588f7579e96
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Jul 18 17:14:35 2012 -0400

    This should be bool.
    
    Change-Id: I20cb39a12b4e50ebb8ef118989252a01f65185e4

diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 0a5f680..d0d3fce 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -678,7 +678,7 @@ rtl::OUString ScMatrixImpl::GetString( SvNumberFormatter& rFormatter, SCSIZE nC,
             return maMat.get<rtl::OUString>(nR, nC);
         case mdds::mtm::element_empty:
         {
-            if (!maMatFlag.get<double>(nR, nC))
+            if (!maMatFlag.get<bool>(nR, nC))
                 // not an empty path.
                 break;
 
commit 9f36df7943127d82aba46590aeebd8abec110d70
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Jul 18 15:10:54 2012 -0400

    Added comment.
    
    Change-Id: Ic9e8a6a970de71647b5436149fbd8c49efece49c

diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index 20c83f3..b358231 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -429,6 +429,8 @@ ScMatrixRef ScInterpreter::CreateMatrixFromDoubleRef( const FormulaToken* pToken
 
         SCROW nPrevRow = -2, nThisRow = -2;
 
+        // Neighboring cell values of identical type are stored and passed as
+        // an array to the matrix object, for performance reasons.
         for (ScBaseCell* pCell = aCellIter.GetFirst(); pCell; pCell = aCellIter.GetNext(), nPrevRow = nThisRow)
         {
             nThisRow = aCellIter.GetRow();
commit 7ba5f709030a78616d2331bd3894752c99fbc1fa
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 ed5d2c652cd053cd10f54fb028f513f20d6c6086
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;
 }
 
commit 32d9ed46f6075c66e233b3c8f8036beceb60d87c
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Jul 18 10:43:32 2012 -0400

    Slightly more efficient compareMatrix.
    
    Have a separate result matrix and have it initialize with boolean
    block.  This way inserting the result of each element does not cause
    reallocation of existing blocks.
    
    Change-Id: Id89114ed5df40cde80129e4479d9b4e7d2e12cc0

diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index dea3c83..8ff39c6 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -237,7 +237,7 @@ namespace {
 
 typedef mdds::multi_type_matrix<custom_string_trait> MatrixImplType;
 
-struct ElemEqual : public unary_function<double, bool>
+struct ElemEqualZero : public unary_function<double, bool>
 {
     bool operator() (double val) const
     {
@@ -245,7 +245,7 @@ struct ElemEqual : public unary_function<double, bool>
     }
 };
 
-struct ElemNotEqual : public unary_function<double, bool>
+struct ElemNotEqualZero : public unary_function<double, bool>
 {
     bool operator() (double val) const
     {
@@ -253,7 +253,7 @@ struct ElemNotEqual : public unary_function<double, bool>
     }
 };
 
-struct ElemGreater : public unary_function<double, bool>
+struct ElemGreaterZero : public unary_function<double, bool>
 {
     bool operator() (double val) const
     {
@@ -261,7 +261,7 @@ struct ElemGreater : public unary_function<double, bool>
     }
 };
 
-struct ElemLess : public unary_function<double, bool>
+struct ElemLessZero : public unary_function<double, bool>
 {
     bool operator() (double val) const
     {
@@ -269,7 +269,7 @@ struct ElemLess : public unary_function<double, bool>
     }
 };
 
-struct ElemGreaterEqual : public unary_function<double, bool>
+struct ElemGreaterEqualZero : public unary_function<double, bool>
 {
     bool operator() (double val) const
     {
@@ -277,7 +277,7 @@ struct ElemGreaterEqual : public unary_function<double, bool>
     }
 };
 
-struct ElemLessEqual : public unary_function<double, bool>
+struct ElemLessEqualZero : public unary_function<double, bool>
 {
     bool operator() (double val) const
     {
@@ -289,6 +289,8 @@ template<typename _Comp>
 void compareMatrix(MatrixImplType& rMat)
 {
     MatrixImplType::size_pair_type aDim = rMat.size();
+    MatrixImplType aNewMat(aDim.row, aDim.column, false); // initialize with boolean block.  faster this way.
+
     _Comp aComp;
     for (size_t i = 0; i < aDim.row; ++i)
     {
@@ -304,9 +306,10 @@ void compareMatrix(MatrixImplType& rMat)
                 continue;
 
             bool b = aComp(fVal);
-            rMat.set(i, j, b);
+            aNewMat.set(i, j, b);
         }
     }
+    aNewMat.swap(rMat);
 }
 
 }
@@ -841,32 +844,32 @@ void ScMatrixImpl::FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2,
 
 void ScMatrixImpl::CompareEqual()
 {
-    compareMatrix<ElemEqual>(maMat);
+    compareMatrix<ElemEqualZero>(maMat);
 }
 
 void ScMatrixImpl::CompareNotEqual()
 {
-    compareMatrix<ElemNotEqual>(maMat);
+    compareMatrix<ElemNotEqualZero>(maMat);
 }
 
 void ScMatrixImpl::CompareLess()
 {
-    compareMatrix<ElemLess>(maMat);
+    compareMatrix<ElemLessZero>(maMat);
 }
 
 void ScMatrixImpl::CompareGreater()
 {
-    compareMatrix<ElemGreater>(maMat);
+    compareMatrix<ElemGreaterZero>(maMat);
 }
 
 void ScMatrixImpl::CompareLessEqual()
 {
-    compareMatrix<ElemLessEqual>(maMat);
+    compareMatrix<ElemLessEqualZero>(maMat);
 }
 
 void ScMatrixImpl::CompareGreaterEqual()
 {
-    compareMatrix<ElemGreaterEqual>(maMat);
+    compareMatrix<ElemGreaterEqualZero>(maMat);
 }
 
 namespace {
commit 8a7ba10c71229f10ee56b263aca4174d7a856f6c
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Jul 18 10:20:33 2012 -0400

    It's now faster to start empty and fill non-empty elements.
    
    The new matrix backend allows to init with empty elements.  Let's
    take advantage of this.
    
    Change-Id: Id11a933e50bcd75a5be85a1b3d0bbff0b4041b46

diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index de577ca..9b22682 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -114,7 +114,7 @@ public:
     /// if denominator is 0.0
     static inline double div( const double& fNumerator, const double& fDenominator );
 
-    ScMatrixRef GetNewMat(SCSIZE nC, SCSIZE nR);
+    ScMatrixRef GetNewMat(SCSIZE nC, SCSIZE nR, bool bEmpty = false);
 
     enum VolatileType {
         VOLATILE,
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index ba868bc..c689729 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -323,10 +323,15 @@ void ScInterpreter:: ScLCM()
     }
 }
 
-ScMatrixRef ScInterpreter::GetNewMat(SCSIZE nC, SCSIZE nR)
+ScMatrixRef ScInterpreter::GetNewMat(SCSIZE nC, SCSIZE nR, bool bEmpty)
 {
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetNewMat" );
-    ScMatrixRef pMat = new ScMatrix(nC, nR, 0.0);
+    ScMatrixRef pMat;
+    if (bEmpty)
+        pMat = new ScMatrix(nC, nR);
+    else
+        pMat = new ScMatrix(nC, nR, 0.0);
+
     pMat->SetErrorInterpreter( this);
     // A temporary matrix is mutable and ScMatrix::CloneIfConst() returns the
     // very matrix.
@@ -366,54 +371,21 @@ ScMatrixRef ScInterpreter::CreateMatrixFromDoubleRef( const FormulaToken* pToken
         {
             SCSIZE nMatCols = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
             SCSIZE nMatRows = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
-            pMat = GetNewMat( nMatCols, nMatRows);
+            pMat = GetNewMat( nMatCols, nMatRows, true);
             if (pMat && !nGlobalError)
             {
-                // Set position where the next entry is expected.
-                SCROW nNextRow = nRow1;
-                SCCOL nNextCol = nCol1;
-                // Set last position as if there was a previous entry.
-                SCROW nThisRow = nRow2;
-                SCCOL nThisCol = nCol1 - 1;
-                ScCellIterator aCellIter( pDok, nCol1, nRow1, nTab1, nCol2,
-                        nRow2, nTab2);
+                ScCellIterator aCellIter(
+                    pDok, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+
                 for (ScBaseCell* pCell = aCellIter.GetFirst(); pCell; pCell =
                         aCellIter.GetNext())
                 {
-                    nThisCol = aCellIter.GetCol();
-                    nThisRow = aCellIter.GetRow();
-                    if (nThisCol != nNextCol || nThisRow != nNextRow)
-                    {
-                        // Fill empty between iterator's positions.
-                        for ( ; nNextCol <= nThisCol; ++nNextCol)
-                        {
-                            SCSIZE nC = nNextCol - nCol1;
-                            SCSIZE nMatStopRow = ((nNextCol < nThisCol) ?
-                                    nMatRows : nThisRow - nRow1);
-                            for (SCSIZE nR = nNextRow - nRow1; nR <
-                                    nMatStopRow; ++nR)
-                            {
-                                pMat->PutEmpty( nC, nR);
-                            }
-                            nNextRow = nRow1;
-                        }
-                    }
-                    if (nThisRow == nRow2)
-                    {
-                        nNextCol = nThisCol + 1;
-                        nNextRow = nRow1;
-                    }
-                    else
-                    {
-                        nNextCol = nThisCol;
-                        nNextRow = nThisRow + 1;
-                    }
+                    SCCOL nThisCol = aCellIter.GetCol();
+                    SCROW nThisRow = aCellIter.GetRow();
                     if (HasCellEmptyData(pCell))
-                    {
-                        pMat->PutEmpty( static_cast<SCSIZE>(nThisCol-nCol1),
-                                static_cast<SCSIZE>(nThisRow-nRow1));
-                    }
-                    else if (HasCellValueData(pCell))
+                        continue;
+
+                    if (HasCellValueData(pCell))
                     {
                         ScAddress aAdr( nThisCol, nThisRow, nTab1);
                         double fVal = GetCellValue( aAdr, pCell);
@@ -425,38 +397,25 @@ ScMatrixRef ScInterpreter::CreateMatrixFromDoubleRef( const FormulaToken* pToken
                         pMat->PutDouble( fVal,
                                 static_cast<SCSIZE>(nThisCol-nCol1),
                                 static_cast<SCSIZE>(nThisRow-nRow1));
+                        continue;
                     }
-                    else
-                    {
-                        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));
-                    }
-                }
-                // Fill empty if iterator's last position wasn't the end.
-                if (nThisCol != nCol2 || nThisRow != nRow2)
-                {
-                    for ( ; nNextCol <= nCol2; ++nNextCol)
+
+                    String aStr;
+                    GetCellString( aStr, pCell);
+                    if ( nGlobalError )
                     {
-                        SCSIZE nC = nNextCol - nCol1;
-                        for (SCSIZE nR = nNextRow - nRow1; nR < nMatRows; ++nR)
-                        {
-                            pMat->PutEmpty( nC, nR);
-                        }
-                        nNextRow = nRow1;
+                        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));
                 }
+
                 if (pTokenMatrixMap)
                     pTokenMatrixMap->insert( ScTokenMatrixMap::value_type(
                                 pToken, new ScMatrixToken( pMat)));
commit 229d86b238186e75621b6f617ebc4ee29756324b
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Jul 18 02:15:05 2012 -0400

    Use macro to define callbacks.
    
    This saves a whole bunch of typings!  It's all boilerplate anyways.
    
    Change-Id: Ide366a9f5756f9354d95499fa9a6a4c46d5c5b82

diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index d6cec83..dea3c83 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -56,73 +56,7 @@ namespace rtl {
 // Callback functions required for supporting rtl::OUString in
 // mdds::multi_type_vector.  They must be in the rtl namespace to satisfy
 // argument dependent lookup that mdds::multi_type_vector requires.
-
-mdds::mtv::element_t mdds_mtv_get_element_type(const OUString&)
-{
-    return element_type_custom_string;
-}
-
-void mdds_mtv_set_value(mdds::mtv::base_element_block& block, size_t pos, const OUString& val)
-{
-    custom_string_block::set_value(block, pos, val);
-}
-
-void mdds_mtv_get_value(const mdds::mtv::base_element_block& block, size_t pos, OUString& val)
-{
-    custom_string_block::get_value(block, pos, val);
-}
-
-template<typename _Iter>
-void mdds_mtv_set_values(
-    mdds::mtv::base_element_block& block, size_t pos, const OUString&, const _Iter& it_begin, const _Iter& it_end)
-{
-    custom_string_block::set_values(block, pos, it_begin, it_end);
-}
-
-void mdds_mtv_append_value(mdds::mtv::base_element_block& block, const OUString& val)
-{
-    custom_string_block::append_value(block, val);
-}
-
-void mdds_mtv_prepend_value(mdds::mtv::base_element_block& block, const OUString& val)
-{
-    custom_string_block::prepend_value(block, val);
-}
-
-template<typename _Iter>
-void mdds_mtv_prepend_values(mdds::mtv::base_element_block& block, const OUString&, const _Iter& it_begin, const _Iter& it_end)
-{
-    custom_string_block::prepend_values(block, it_begin, it_end);
-}
-
-template<typename _Iter>
-void mdds_mtv_append_values(mdds::mtv::base_element_block& block, const OUString&, const _Iter& it_begin, const _Iter& it_end)
-{
-    custom_string_block::append_values(block, it_begin, it_end);
-}
-
-template<typename _Iter>
-void mdds_mtv_assign_values(mdds::mtv::base_element_block& dest, const OUString&, const _Iter& it_begin, const _Iter& it_end)
-{
-    custom_string_block::assign_values(dest, it_begin, it_end);
-}
-
-void mdds_mtv_get_empty_value(OUString& val)
-{
-    val = OUString();
-}
-
-template<typename _Iter>
-void mdds_mtv_insert_values(
-    mdds::mtv::base_element_block& block, size_t pos, const OUString&, const _Iter& it_begin, const _Iter& it_end)
-{
-    custom_string_block::insert_values(block, pos, it_begin, it_end);
-}
-
-mdds::mtv::base_element_block* mdds_mtv_create_new_block(size_t init_size, const OUString& val)
-{
-    return custom_string_block::create_block_with_value(init_size, val);
-}
+MDDS_MTV_DEFINE_ELEMENT_CALLBACKS(OUString, element_type_custom_string, OUString(), custom_string_block)
 
 }
 
commit 93c8b68ba62e392db6af85d0663e2ff31201eb22
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Jul 18 01:54:01 2012 -0400

    Reorganized code to remove redundant calls to get_type().
    
    This makes GetString() a teeny bit faster.
    
    Change-Id: Id49df508d45584d529caa4061e77f4ddc4431c67

diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 039b289..d6cec83 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -668,16 +668,25 @@ rtl::OUString ScMatrixImpl::GetString(SCSIZE nC, SCSIZE nR) const
 {
     if (ValidColRowOrReplicated( nC, nR ))
     {
+        double fErr = 0.0;
         switch (maMat.get_type(nR, nC))
         {
             case mdds::mtm::element_string:
                 return maMat.get<rtl::OUString>(nR, nC);
             case mdds::mtm::element_empty:
                 return EMPTY_OUSTRING;
+            case mdds::mtm::element_numeric:
+                OSL_FAIL("ScMatrixImpl::GetString: access error, no string");
+                fErr = maMat.get<double>(nR, nC);
+            break;
+            case mdds::mtm::element_boolean:
+                OSL_FAIL("ScMatrixImpl::GetString: access error, no string");
+                fErr = maMat.get<bool>(nR, nC);
+            break;
             default:
-                SetErrorAtInterpreter( GetError(nC, nR));
                 OSL_FAIL("ScMatrixImpl::GetString: access error, no string");
         }
+        SetErrorAtInterpreter(GetDoubleErrorValue(fErr));
     }
     else
     {
@@ -701,10 +710,18 @@ rtl::OUString ScMatrixImpl::GetString( SvNumberFormatter& rFormatter, SCSIZE nC,
         return ::rtl::OUString();
     }
 
-    if (IsString( nC, nR))
+    double fVal = 0.0;
+    switch (maMat.get_type(nR, nC))
     {
-        if (IsEmptyPath( nC, nR))
-        {   // result of empty FALSE jump path
+        case mdds::mtm::element_string:
+            return maMat.get<rtl::OUString>(nR, nC);
+        case mdds::mtm::element_empty:
+        {
+            if (!maMatFlag.get<double>(nR, nC))
+                // not an empty path.
+                break;
+
+            // result of empty FALSE jump path
             sal_uLong nKey = rFormatter.GetStandardFormat( NUMBERFORMAT_LOGICAL,
                     ScGlobal::eLnge);
             ::rtl::OUString aStr;
@@ -712,17 +729,23 @@ rtl::OUString ScMatrixImpl::GetString( SvNumberFormatter& rFormatter, SCSIZE nC,
             rFormatter.GetOutputString( 0.0, nKey, aStr, &pColor);
             return aStr;
         }
-        return GetString( nC, nR);
+        case mdds::mtm::element_numeric:
+            fVal = maMat.get<double>(nR, nC);
+        break;
+        case mdds::mtm::element_boolean:
+            fVal = maMat.get<bool>(nR, nC);
+        break;
+        default:
+            ;
     }
 
-    sal_uInt16 nError = GetError( nC, nR);
+    sal_uInt16 nError = GetDoubleErrorValue(fVal);
     if (nError)
     {
         SetErrorAtInterpreter( nError);
         return ScGlobal::GetErrorString( nError);
     }
 
-    double fVal= GetDouble( nC, nR);
     sal_uLong nKey = rFormatter.GetStandardFormat( NUMBERFORMAT_NUMBER,
             ScGlobal::eLnge);
     ::rtl::OUString aStr;
commit 96610e8ed700f73592c65bee94d75d6fa9f9de96
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 17 16:44:17 2012 -0400

    Some cleanup and comments.
    
    Change-Id: I38e9bbc0a55498e612665e90b5b1452e6c245c21

diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 8560c0d..039b289 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -53,6 +53,10 @@ typedef mdds::mtv::default_element_block<element_type_custom_string, rtl::OUStri
 
 namespace rtl {
 
+// Callback functions required for supporting rtl::OUString in
+// mdds::multi_type_vector.  They must be in the rtl namespace to satisfy
+// argument dependent lookup that mdds::multi_type_vector requires.
+
 mdds::mtv::element_t mdds_mtv_get_element_type(const OUString&)
 {
     return element_type_custom_string;
@@ -122,6 +126,10 @@ mdds::mtv::base_element_block* mdds_mtv_create_new_block(size_t init_size, const
 
 }
 
+/**
+ * Custom string trait struct to tell mdds::multi_type_matrix about the
+ * custom string type and how to handle blocks storing them.
+ */
 struct custom_string_trait
 {
     typedef OUString string_type;
@@ -279,7 +287,8 @@ struct custom_string_trait
             switch (mdds::mtv::get_block_type(block))
             {
                 case element_type_custom_string:
-                    // Do nothing.  The client code manages the life cycle of these cells.
+                    // Do nothing.  One needs to handle this only when the
+                    // block stores pointers and manages their life cycles.
                 break;
                 default:
                     mdds::mtv::element_block_func::overwrite_values(block, pos, len);
@@ -288,7 +297,6 @@ struct custom_string_trait
     };
 };
 
-
 // ============================================================================
 
 namespace {
commit e0704701ded22352f058acde6fe5d36bbd278d47
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 17 16:26:14 2012 -0400

    Turns out that C++03 doesn't support use of static double inside template.
    
    static int works, however.  C++11 solves this via constexpr keyword.
    
    Change-Id: I86f913129cbc65639ec2bf4b23843a5b25bd9146

diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 4dfa738..8560c0d 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -966,7 +966,7 @@ namespace {
 
 struct SumOp
 {
-    static const double initVal = 0.0;
+    static const int InitVal = 0;
 
     void operator() (double& rAccum, double fVal)
     {
@@ -976,7 +976,7 @@ struct SumOp
 
 struct SumSquareOp
 {
-    static const double initVal = 0.0;
+    static const int InitVal = 0;
 
     void operator() (double& rAccum, double fVal)
     {
@@ -986,7 +986,7 @@ struct SumSquareOp
 
 struct ProductOp
 {
-    static const double initVal = 1.0;
+    static const int InitVal = 1;
 
     void operator() (double& rAccum, double fVal)
     {
@@ -1003,7 +1003,7 @@ class WalkElementBlocks : std::unary_function<MatrixImplType::element_block_node
     bool mbFirst:1;
     bool mbTextAsZero:1;
 public:
-    WalkElementBlocks(bool bTextAsZero) : maRes(0.0, _Op::initVal, 0), mbFirst(true), mbTextAsZero(bTextAsZero) {}
+    WalkElementBlocks(bool bTextAsZero) : maRes(0.0, _Op::InitVal, 0), mbFirst(true), mbTextAsZero(bTextAsZero) {}
 
     const ScMatrix::IterateResult& getResult() const { return maRes; }
 
commit d3629a3942b681fcff006967c50394b3a9c344ee
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 17 15:55:38 2012 -0400

    It's no longer possible to unionize value and string here...
    
    Thereby leaving a note to discourage use of ScMatrixValue.  Incidentally,
    now all the unit test passes.
    
    Change-Id: I5d12f8ab654f985ef43b887a22abb6de45fea1fc

diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index 409fea5..034bc4d 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -49,16 +49,18 @@ const ScMatValType SC_MATVAL_EMPTY     = SC_MATVAL_STRING | 0x04; // STRING plus
 const ScMatValType SC_MATVAL_EMPTYPATH = SC_MATVAL_EMPTY | 0x08;  // EMPTY plus flag
 const ScMatValType SC_MATVAL_NONVALUE  = SC_MATVAL_EMPTYPATH;     // mask of all non-value bits
 
+/**
+ * Try NOT to use this struct.  This struct should go away in a hopefully
+ * not so distant futture.
+ */
 struct ScMatrixValue
 {
-    union {
-        double fVal;
-        const ::rtl::OUString* pS;
-    };
+    double fVal;
+    rtl::OUString aStr;
     ScMatValType nType;
 
     /// Only valid if ScMatrix methods indicate so!
-    const ::rtl::OUString& GetString() const { return pS ? *pS : EMPTY_OUSTRING; }
+    const ::rtl::OUString& GetString() const { return aStr; }
 
     /// Only valid if ScMatrix methods indicate that this is no string!
     sal_uInt16 GetError() const         { return GetDoubleErrorValue( fVal); }
@@ -68,12 +70,8 @@ struct ScMatrixValue
 
     ScMatrixValue() : fVal(0.0), nType(SC_MATVAL_EMPTY) {}
 
-    ScMatrixValue(const ScMatrixValue& r) : fVal(r.fVal), nType(r.nType)
-    {
-        if (nType == SC_MATVAL_STRING)
-            // This is probably not necessary but just in case...
-            pS = r.pS;
-    }
+    ScMatrixValue(const ScMatrixValue& r) :
+        fVal(r.fVal), aStr(r.aStr), nType(r.nType) {}
 
     bool operator== (const ScMatrixValue& r) const
     {
@@ -89,10 +87,8 @@ struct ScMatrixValue
             default:
                 ;
         }
-        if (!pS)
-            return r.pS == NULL;
 
-        return GetString().equals(r.GetString());
+        return aStr == r.aStr;
     }
 
     bool operator!= (const ScMatrixValue& r) const
@@ -102,13 +98,12 @@ struct ScMatrixValue
 
     ScMatrixValue& operator= (const ScMatrixValue& r)
     {
+        if (this == &r)
+            return *this;
+
         nType = r.nType;
         fVal = r.fVal;
-
-        if (nType == SC_MATVAL_STRING)
-            // This is probably not necessary but just in case...
-            pS = r.pS;
-
+        aStr = r.aStr;
         return *this;
     }
 };
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 1450b84..79cda88 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -1224,7 +1224,7 @@ struct PartiallyFilledEmptyMatrix
         else if (nCol == 8 && nRow == 2)
         {
             CPPUNIT_ASSERT_MESSAGE("element is not of value type", rVal.nType == SC_MATVAL_STRING);
-            CPPUNIT_ASSERT_MESSAGE("element value is not what is expected", rVal.pS->equalsAscii("Test"));
+            CPPUNIT_ASSERT_MESSAGE("element value is not what is expected", rVal.aStr == "Test");
         }
         else if (nCol == 8 && nRow == 11)
         {
diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx
index 6ab3d2d..0e34b35 100644
--- a/sc/source/core/data/cell.cxx
+++ b/sc/source/core/data/cell.cxx
@@ -1926,11 +1926,11 @@ void ScFormulaCell::GetURLResult( rtl::OUString& rURL, rtl::OUString& rCellText
     if (xMat)
     {
         // determine if the matrix result is a string or value.
-        ScMatrixValue nMatVal = xMat->Get(0, 1);
-        if (!ScMatrix::IsValueType( nMatVal.nType))
-            rURL = nMatVal.GetString();
+        if (!xMat->IsValue(0, 1))
+            rURL = xMat->GetString(0, 1);
         else
-            pFormatter->GetOutputString( nMatVal.fVal, nURLFormat, rURL, &pColor );
+            pFormatter->GetOutputString(
+                xMat->GetDouble(0, 1), nURLFormat, rURL, &pColor);
     }
 
     if(rURL.isEmpty())
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 3b1aecb..4dfa738 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -740,7 +740,7 @@ ScMatrixValue ScMatrixImpl::Get(SCSIZE nC, SCSIZE nR) const
             break;
             case mdds::mtm::element_string:
                 aVal.nType = SC_MATVAL_STRING;
-                aVal.pS = &EMPTY_OUSTRING;
+                aVal.aStr = maMat.get_string(nR, nC);
             break;
             case mdds::mtm::element_empty:
                 // Empty path equals empty plus flag.
commit d13804609737114f30dbc7580e4bc76e66cb02a8
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 17 15:22:52 2012 -0400

    We no longer need density types.
    
    Change-Id: I4a02e9e025b6004806350fc8c78f6080176df8d6

diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index e1098c5..409fea5 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -131,14 +131,6 @@ class SC_DLLPUBLIC ScMatrix
     ScMatrix& operator=( const ScMatrix&);
 
 public:
-    enum DensityType
-    {
-        FILLED_ZERO,
-        FILLED_EMPTY,
-        SPARSE_ZERO,
-        SPARSE_EMPTY
-    };
-
     /**
      * When adding all numerical matrix elements for a scalar result such as
      * summation, the interpreter wants to separate the first non-zero value
commit 891e5892b2798a6bc326a688ed50e79a4a9d336b
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 17 15:15:32 2012 -0400

    This is no longer true.
    
    Change-Id: Id132c4bb7455acbdaa2287666523f42c20172f37

diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index 984561e..e1098c5 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -117,11 +117,6 @@ struct ScMatrixValue
  * Matrix data type that can store values of mixed types.  Each element can
  * be one of the following types: numeric, string, boolean, empty, and empty
  * path.
- *
- * This class also supports four different density types: filled zero,
- * filled empty, sparse zero, and sparse empty.  The filled density type
- * allocates memory for every single element at all times, whereas the
- * sparse density types allocates memory only for non-default elements.
  */
 class SC_DLLPUBLIC ScMatrix
 {
commit 2789bcb41b9b71551f2acd5e2d9df959c599a608
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 17 15:02:05 2012 -0400

    Support resizing matrix with a default value.
    
    Change-Id: Ibb5cf4d09b67426021f6d158878afd8386f22555

diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index d6d3e15..984561e 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -238,6 +238,8 @@ public:
      */
     void Resize( SCSIZE nC, SCSIZE nR);
 
+    void Resize(SCSIZE nC, SCSIZE nR, double fVal);
+
     /** Clone the matrix and extend it to the new size. nNewCols and nNewRows
         MUST be at least of the size of the original matrix. */
     ScMatrix* CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const;
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index dd09aa8..1450b84 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -1248,7 +1248,7 @@ void Test::testMatrix()
     SCSIZE nC, nR;
     pMat->GetDimensions(nC, nR);
     CPPUNIT_ASSERT_MESSAGE("matrix is not empty", nC == 0 && nR == 0);
-    pMat->Resize(4, 10);
+    pMat->Resize(4, 10, 0.0);
     pMat->GetDimensions(nC, nR);
     CPPUNIT_ASSERT_MESSAGE("matrix size is not as expected", nC == 4 && nR == 10);
     CPPUNIT_ASSERT_MESSAGE("both 'and' and 'or' should evaluate to false",
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 9e35843..3b1aecb 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -388,6 +388,7 @@ public:
     void SetImmutable(bool bVal);
     bool IsImmutable() const;
     void Resize(SCSIZE nC, SCSIZE nR);
+    void Resize(SCSIZE nC, SCSIZE nR, double fVal);
     void SetErrorInterpreter( ScInterpreter* p);
     ScInterpreter* GetErrorInterpreter() const { return pErrorInterpreter; }
 
@@ -475,6 +476,11 @@ void ScMatrixImpl::Resize(SCSIZE nC, SCSIZE nR)
     maMat.resize(nR, nC);
 }
 
+void ScMatrixImpl::Resize(SCSIZE nC, SCSIZE nR, double fVal)
+{
+    maMat.resize(nR, nC, fVal);
+}
+
 void ScMatrixImpl::SetErrorInterpreter( ScInterpreter* p)
 {
     pErrorInterpreter = p;
@@ -1154,6 +1160,11 @@ void ScMatrix::Resize( SCSIZE nC, SCSIZE nR)
     pImpl->Resize(nC, nR);
 }
 
+void ScMatrix::Resize(SCSIZE nC, SCSIZE nR, double fVal)
+{
+    pImpl->Resize(nC, nR, fVal);
+}
+
 ScMatrix* ScMatrix::CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const
 {
     ScMatrix* pScMat = new ScMatrix(nNewCols, nNewRows);
commit c79305f2a1218a3cbf74c7db3c9745429e8b7883
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 17 13:57:43 2012 -0400

    For sum product, the initial accumulator value should be 1, not 0.
    
    Change-Id: I16ce22150627f75eab08cc4d58fc63a76572c010

diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 67f2ffb..9e35843 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -960,6 +960,8 @@ namespace {
 
 struct SumOp
 {
+    static const double initVal = 0.0;
+
     void operator() (double& rAccum, double fVal)
     {
         rAccum += fVal;
@@ -968,6 +970,8 @@ struct SumOp
 
 struct SumSquareOp
 {
+    static const double initVal = 0.0;
+
     void operator() (double& rAccum, double fVal)
     {
         rAccum += fVal*fVal;
@@ -976,6 +980,8 @@ struct SumSquareOp
 
 struct ProductOp
 {
+    static const double initVal = 1.0;
+
     void operator() (double& rAccum, double fVal)
     {
         rAccum *= fVal;
@@ -991,7 +997,7 @@ class WalkElementBlocks : std::unary_function<MatrixImplType::element_block_node
     bool mbFirst:1;
     bool mbTextAsZero:1;
 public:
-    WalkElementBlocks(bool bTextAsZero) : maRes(0.0, 0.0, 0), mbFirst(true), mbTextAsZero(bTextAsZero) {}
+    WalkElementBlocks(bool bTextAsZero) : maRes(0.0, _Op::initVal, 0), mbFirst(true), mbTextAsZero(bTextAsZero) {}
 
     const ScMatrix::IterateResult& getResult() const { return maRes; }
 
@@ -1092,7 +1098,8 @@ ScMatrix::IterateResult ScMatrixImpl::Product(bool bTextAsZero) const
 {
     WalkElementBlocks<ProductOp> aFunc(bTextAsZero);
     maMat.walk(aFunc);
-    return aFunc.getResult();
+    ScMatrix::IterateResult aRes = aFunc.getResult();
+    return aRes;
 }
 
 size_t ScMatrixImpl::Count(bool bCountStrings) const
commit 608fdfe12329094604d9424f1225e23d94ac7537
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 17 13:39:31 2012 -0400

    Don't forget to initialize the flag matrix.
    
    Change-Id: I02ca2b6fbe49530988a81d12b4e38d24c9046cf6

diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index c667846..67f2ffb 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -444,10 +444,10 @@ private:
 };
 
 ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR) :
-    maMat(nR, nC), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
+    maMat(nR, nC), maMatFlag(nR, nC), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
 
 ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR, double fInitVal) :
-    maMat(nR, nC, fInitVal), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
+    maMat(nR, nC, fInitVal), maMatFlag(nR, nC), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
 
 ScMatrixImpl::~ScMatrixImpl()
 {
@@ -457,6 +457,7 @@ ScMatrixImpl::~ScMatrixImpl()
 void ScMatrixImpl::Clear()
 {
     maMat.clear();
+    maMatFlag.clear();
 }
 
 void ScMatrixImpl::SetImmutable(bool bVal)
commit cc72060199d83e7d919edc3b1a295dc9f8f8b97b
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 17 11:56:53 2012 -0400

    A little cleanup.
    
    Change-Id: Ib0059f921f815a0ddb679f4bc1888eec2270981e

diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 4146d26..c667846 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -294,7 +294,6 @@ struct custom_string_trait
 namespace {
 
 typedef mdds::multi_type_matrix<custom_string_trait> MatrixImplType;
-//typedef ::mdds::mixed_type_matrix< ::rtl::OUString, sal_uInt8> MatrixImplType;
 
 struct ElemEqual : public unary_function<double, bool>
 {
@@ -368,25 +367,6 @@ void compareMatrix(MatrixImplType& rMat)
     }
 }
 
-#if 0
-/**
- * Return a numeric value from a matrix element no matter what its type is.
- */
-double getNumericValue(const MatrixImplType::element& elem)
-{
-    switch (elem.m_type)
-    {
-        case mdds::element_boolean:
-            return static_cast<double>(elem.m_boolean);
-        case mdds::element_numeric:
-            return elem.m_numeric;
-        default:
-            ;
-    }
-    return 0.0;
-}
-#endif
-
 }
 
 class ScMatrixImpl
commit 0ddcb7a07a42294200b86dac7e67a4c82e03fcf4
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 17 11:54:35 2012 -0400

    Implement Sum(), SumSquare(), etc...
    
    The unit test still segfaults.
    
    Change-Id: Ib1fc78f94776e04ba8cb6ec8a24162b308cc569f

diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index ee6e658..4146d26 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -975,24 +975,150 @@ double ScMatrixImpl::Or() const
     return EvalMatrix<OrEvaluator>(maMat);
 }
 
+namespace {
+
+struct SumOp
+{
+    void operator() (double& rAccum, double fVal)
+    {
+        rAccum += fVal;
+    }
+};
+
+struct SumSquareOp
+{
+    void operator() (double& rAccum, double fVal)
+    {
+        rAccum += fVal*fVal;
+    }
+};
+
+struct ProductOp
+{
+    void operator() (double& rAccum, double fVal)
+    {
+        rAccum *= fVal;
+    }
+};
+
+template<typename _Op>
+class WalkElementBlocks : std::unary_function<MatrixImplType::element_block_node_type, void>
+{
+    _Op maOp;
+
+    ScMatrix::IterateResult maRes;
+    bool mbFirst:1;
+    bool mbTextAsZero:1;
+public:
+    WalkElementBlocks(bool bTextAsZero) : maRes(0.0, 0.0, 0), mbFirst(true), mbTextAsZero(bTextAsZero) {}
+
+    const ScMatrix::IterateResult& getResult() const { return maRes; }
+
+    void operator() (const MatrixImplType::element_block_node_type& node)
+    {
+        switch (node.type)
+        {
+            case mdds::mtm::element_numeric:
+            {
+                mdds::mtv::numeric_element_block::const_iterator it = mdds::mtv::numeric_element_block::begin(*node.data);
+                mdds::mtv::numeric_element_block::const_iterator itEnd = mdds::mtv::numeric_element_block::end(*node.data);
+                for (; it != itEnd; ++it)
+                {
+                    if (mbFirst)
+                    {
+                        maOp(maRes.mfFirst, *it);
+                        mbFirst = false;
+                    }
+                    else
+                        maOp(maRes.mfRest, *it);
+                }
+                maRes.mnCount += node.size;
+            }
+            break;
+            case mdds::mtm::element_boolean:
+            {
+                mdds::mtv::boolean_element_block::const_iterator it = mdds::mtv::boolean_element_block::begin(*node.data);
+                mdds::mtv::boolean_element_block::const_iterator itEnd = mdds::mtv::boolean_element_block::end(*node.data);
+                for (; it != itEnd; ++it)
+                {
+                    if (mbFirst)
+                    {
+                        maOp(maRes.mfFirst, *it);
+                        mbFirst = false;
+                    }
+                    else
+                        maOp(maRes.mfRest, *it);
+                }
+                maRes.mnCount += node.size;
+            }
+            break;
+            case mdds::mtm::element_string:
+                if (mbTextAsZero)
+                    maRes.mnCount += node.size;
+            break;
+            case mdds::mtm::element_empty:
+            default:
+                ;
+        }
+    }
+};
+
+class CountElements : std::unary_function<MatrixImplType::element_block_node_type, void>
+{
+    size_t mnCount;
+    bool mbCountString;
+public:
+    CountElements(bool bCountString) : mnCount(0), mbCountString(bCountString) {}
+
+    size_t getCount() const { return mnCount; }
+
+    void operator() (const MatrixImplType::element_block_node_type& node)
+    {
+        switch (node.type)
+        {
+            case mdds::mtm::element_numeric:
+            case mdds::mtm::element_boolean:
+                mnCount += node.size;
+            break;
+            case mdds::mtm::element_string:
+                if (mbCountString)
+                    mnCount += node.size;
+            break;
+            case mdds::mtm::element_empty:
+            default:
+                ;
+        }
+    }
+};
+
+}
+
 ScMatrix::IterateResult ScMatrixImpl::Sum(bool bTextAsZero) const
 {
-    return ScMatrix::IterateResult(0, 0, 0);
+    WalkElementBlocks<SumOp> aFunc(bTextAsZero);
+    maMat.walk(aFunc);
+    return aFunc.getResult();
 }
 
 ScMatrix::IterateResult ScMatrixImpl::SumSquare(bool bTextAsZero) const
 {
-    return ScMatrix::IterateResult(0, 0, 0);
+    WalkElementBlocks<SumSquareOp> aFunc(bTextAsZero);
+    maMat.walk(aFunc);
+    return aFunc.getResult();
 }
 
 ScMatrix::IterateResult ScMatrixImpl::Product(bool bTextAsZero) const
 {
-    return ScMatrix::IterateResult(0, 0, 0);
+    WalkElementBlocks<ProductOp> aFunc(bTextAsZero);
+    maMat.walk(aFunc);
+    return aFunc.getResult();
 }
 
 size_t ScMatrixImpl::Count(bool bCountStrings) const
 {
-    return 0;
+    CountElements aFunc(bCountStrings);
+    maMat.walk(aFunc);
+    return aFunc.getCount();
 }
 
 void ScMatrixImpl::CalcPosition(SCSIZE nIndex, SCSIZE& rC, SCSIZE& rR) const
commit b4c774a51fab40569abf6298789f6dedfbebdd12
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Jul 16 23:24:40 2012 -0400

    Now, we need to explicitly pass 0.0 as the initial value of a matrix.
    
    The new matrix class allows arbitrary initial values instead of just
    0.0 or empty values.  With this, the caller now has to explicitly pass
    zero value to the constructor if it wants to create a matrix filled with
    zeros.
    
    Change-Id: Ie515358b512fdb83ae60f54ab4ab49c92ca5761d

diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 7ea887c..dd09aa8 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -1242,72 +1242,57 @@ struct PartiallyFilledEmptyMatrix
 void Test::testMatrix()
 {
     ScMatrixRef pMat;
-    ScMatrix::DensityType eDT[2];
 
-    // First, test the zero matrix types.
-    eDT[0] = ScMatrix::FILLED_ZERO;
-    eDT[1] = ScMatrix::SPARSE_ZERO;
-    for (int i = 0; i < 2; ++i)
-    {
-        pMat = new ScMatrix(0, 0, eDT[i]);
-        SCSIZE nC, nR;
-        pMat->GetDimensions(nC, nR);
-        CPPUNIT_ASSERT_MESSAGE("matrix is not empty", nC == 0 && nR == 0);
-        pMat->Resize(4, 10);
-        pMat->GetDimensions(nC, nR);
-        CPPUNIT_ASSERT_MESSAGE("matrix size is not as expected", nC == 4 && nR == 10);
-        CPPUNIT_ASSERT_MESSAGE("both 'and' and 'or' should evaluate to false",
-                               !pMat->And() && !pMat->Or());
-
-        // Resizing into a larger matrix should fill the void space with zeros.
-        checkMatrixElements<AllZeroMatrix>(*pMat);
-
-        pMat->FillDouble(3.0, 1, 2, 2, 8);
-        checkMatrixElements<PartiallyFilledZeroMatrix>(*pMat);
-        CPPUNIT_ASSERT_MESSAGE("matrix is expected to be numeric", pMat->IsNumeric());
-        CPPUNIT_ASSERT_MESSAGE("partially non-zero matrix should evaluate false on 'and' and true on 'or",
-                               !pMat->And() && pMat->Or());
-        pMat->FillDouble(5.0, 0, 0, nC-1, nR-1);
-        CPPUNIT_ASSERT_MESSAGE("fully non-zero matrix should evaluate true both on 'and' and 'or",
-                               pMat->And() && pMat->Or());
-    }
+    // First, test the zero matrix type.
+    pMat = new ScMatrix(0, 0, 0.0);
+    SCSIZE nC, nR;
+    pMat->GetDimensions(nC, nR);
+    CPPUNIT_ASSERT_MESSAGE("matrix is not empty", nC == 0 && nR == 0);
+    pMat->Resize(4, 10);
+    pMat->GetDimensions(nC, nR);
+    CPPUNIT_ASSERT_MESSAGE("matrix size is not as expected", nC == 4 && nR == 10);
+    CPPUNIT_ASSERT_MESSAGE("both 'and' and 'or' should evaluate to false",
+                           !pMat->And() && !pMat->Or());
+
+    // Resizing into a larger matrix should fill the void space with zeros.
+    checkMatrixElements<AllZeroMatrix>(*pMat);
+
+    pMat->FillDouble(3.0, 1, 2, 2, 8);
+    checkMatrixElements<PartiallyFilledZeroMatrix>(*pMat);
+    CPPUNIT_ASSERT_MESSAGE("matrix is expected to be numeric", pMat->IsNumeric());
+    CPPUNIT_ASSERT_MESSAGE("partially non-zero matrix should evaluate false on 'and' and true on 'or",
+                           !pMat->And() && pMat->Or());
+    pMat->FillDouble(5.0, 0, 0, nC-1, nR-1);
+    CPPUNIT_ASSERT_MESSAGE("fully non-zero matrix should evaluate true both on 'and' and 'or",
+                           pMat->And() && pMat->Or());
 
     // Test the AND and OR evaluations.
-    for (int i = 0; i < 2; ++i)
-    {
-        pMat = new ScMatrix(2, 2, eDT[i]);
-
-        // Only some of the elements are non-zero.
-        pMat->PutBoolean(true, 0, 0);
-        pMat->PutDouble(1.0, 1, 1);
-        CPPUNIT_ASSERT_MESSAGE("incorrect OR result", pMat->Or());
-        CPPUNIT_ASSERT_MESSAGE("incorrect AND result", !pMat->And());
-
-        // All of the elements are non-zero.
-        pMat->PutBoolean(true, 0, 1);
-        pMat->PutDouble(2.3, 1, 0);
-        CPPUNIT_ASSERT_MESSAGE("incorrect OR result", pMat->Or());
-        CPPUNIT_ASSERT_MESSAGE("incorrect AND result", pMat->And());
-    }
-
-    // Now test the emtpy matrix types.
-    eDT[0] = ScMatrix::FILLED_EMPTY;
-    eDT[1] = ScMatrix::SPARSE_EMPTY;
-    for (int i = 0; i < 2; ++i)
-    {
-        pMat = new ScMatrix(10, 20, eDT[i]);
-        SCSIZE nC, nR;
-        pMat->GetDimensions(nC, nR);
-        CPPUNIT_ASSERT_MESSAGE("matrix size is not as expected", nC == 10 && nR == 20);
-        checkMatrixElements<AllEmptyMatrix>(*pMat);
-
-        pMat->PutBoolean(true, 1, 1);
-        pMat->PutDouble(-12.5, 4, 5);
-        rtl::OUString aStr("Test");
-        pMat->PutString(aStr, 8, 2);
-        pMat->PutEmptyPath(8, 11);
-        checkMatrixElements<PartiallyFilledEmptyMatrix>(*pMat);
-    }
+    pMat = new ScMatrix(2, 2, 0.0);
+
+    // Only some of the elements are non-zero.
+    pMat->PutBoolean(true, 0, 0);
+    pMat->PutDouble(1.0, 1, 1);
+    CPPUNIT_ASSERT_MESSAGE("incorrect OR result", pMat->Or());
+    CPPUNIT_ASSERT_MESSAGE("incorrect AND result", !pMat->And());
+
+    // All of the elements are non-zero.
+    pMat->PutBoolean(true, 0, 1);
+    pMat->PutDouble(2.3, 1, 0);
+    CPPUNIT_ASSERT_MESSAGE("incorrect OR result", pMat->Or());
+    CPPUNIT_ASSERT_MESSAGE("incorrect AND result", pMat->And());
+
+    // Now test the emtpy matrix type.
+    pMat = new ScMatrix(10, 20);
+    pMat->GetDimensions(nC, nR);
+    CPPUNIT_ASSERT_MESSAGE("matrix size is not as expected", nC == 10 && nR == 20);
+    checkMatrixElements<AllEmptyMatrix>(*pMat);
+
+    pMat->PutBoolean(true, 1, 1);
+    pMat->PutDouble(-12.5, 4, 5);
+    rtl::OUString aStr("Test");
+    pMat->PutString(aStr, 8, 2);
+    pMat->PutEmptyPath(8, 11);
+    checkMatrixElements<PartiallyFilledEmptyMatrix>(*pMat);
 }
 
 namespace {
diff --git a/sc/source/core/data/validat.cxx b/sc/source/core/data/validat.cxx
index 4ccb551..4dd8f2e 100644
--- a/sc/source/core/data/validat.cxx
+++ b/sc/source/core/data/validat.cxx
@@ -628,7 +628,7 @@ bool ScValidationData::GetSelectionFromFormula(
         // is stored as a single value.
 
         // Use an interim matrix to create the TypedStrData below.
-        xMatRef = new ScMatrix(1,1);
+        xMatRef = new ScMatrix(1, 1, 0.0);
 
         sal_uInt16 nErrCode = aValidationSrc.GetErrCode();
         if (nErrCode)
diff --git a/sc/source/core/tool/addincol.cxx b/sc/source/core/tool/addincol.cxx
index ba2c9cb..33c9232 100644
--- a/sc/source/core/tool/addincol.cxx
+++ b/sc/source/core/tool/addincol.cxx
@@ -1650,7 +1650,7 @@ void ScUnoAddInCall::SetResult( const uno::Any& rNewRes )
                     {
                         xMatrix = new ScMatrix(
                                 static_cast<SCSIZE>(nMaxColCount),
-                                static_cast<SCSIZE>(nRowCount) );
+                                static_cast<SCSIZE>(nRowCount), 0.0);
                         for (nRow=0; nRow<nRowCount; nRow++)
                         {
                             long nColCount = pRowArr[nRow].getLength();
@@ -1692,7 +1692,7 @@ void ScUnoAddInCall::SetResult( const uno::Any& rNewRes )
                     {
                         xMatrix = new ScMatrix(
                                 static_cast<SCSIZE>(nMaxColCount),
-                                static_cast<SCSIZE>(nRowCount) );
+                                static_cast<SCSIZE>(nRowCount), 0.0);
                         for (nRow=0; nRow<nRowCount; nRow++)
                         {
                             long nColCount = pRowArr[nRow].getLength();
@@ -1734,7 +1734,7 @@ void ScUnoAddInCall::SetResult( const uno::Any& rNewRes )
                     {
                         xMatrix = new ScMatrix(
                                 static_cast<SCSIZE>(nMaxColCount),
-                                static_cast<SCSIZE>(nRowCount) );
+                                static_cast<SCSIZE>(nRowCount), 0.0);
                         for (nRow=0; nRow<nRowCount; nRow++)
                         {
                             long nColCount = pRowArr[nRow].getLength();
diff --git a/sc/source/core/tool/ddelink.cxx b/sc/source/core/tool/ddelink.cxx
index 5bac102..aef6b49 100644
--- a/sc/source/core/tool/ddelink.cxx
+++ b/sc/source/core/tool/ddelink.cxx
@@ -166,7 +166,7 @@ sfx2::SvBaseLink::UpdateResult ScDdeLink::DataChanged(
     else                                // Daten aufteilen
     {
         //  Matrix immer neu anlegen, damit bIsString nicht durcheinanderkommt
-        pResult = new ScMatrix( nCols, nRows );
+        pResult = new ScMatrix(nCols, nRows, 0.0);
 
         SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
 
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 4b453b2..b10aea7 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -5333,7 +5333,7 @@ void ScInterpreter::ScSumIf()
             break;
             case svExternalSingleRef:
             {
-                pSumExtraMatrix = new ScMatrix(1, 1);
+                pSumExtraMatrix = new ScMatrix(1, 1, 0.0);
                 ScExternalRefCache::TokenRef pToken;
                 PopExternalSingleRef(pToken);
                 if (!pToken)
@@ -5957,7 +5957,7 @@ void ScInterpreter::ScLookup()
         ScMatrixRef pDataMat2;
         if (bVertical)
         {
-            ScMatrixRef pTempMat(new ScMatrix(1, nR));
+            ScMatrixRef pTempMat(new ScMatrix(1, nR, 0.0));
             for (SCSIZE i = 0; i < nR; ++i)
                 if (pDataMat->IsValue(0, i))
                     pTempMat->PutDouble(pDataMat->GetDouble(0, i), 0, i);
@@ -5967,7 +5967,7 @@ void ScInterpreter::ScLookup()
         }
         else
         {
-            ScMatrixRef pTempMat(new ScMatrix(nC, 1));
+            ScMatrixRef pTempMat(new ScMatrix(nC, 1, 0.0));
             for (SCSIZE i = 0; i < nC; ++i)
                 if (pDataMat->IsValue(i, 0))
                     pTempMat->PutDouble(pDataMat->GetDouble(i, 0), i, 0);
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index eaa5a38..ba868bc 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -326,7 +326,7 @@ void ScInterpreter:: ScLCM()
 ScMatrixRef ScInterpreter::GetNewMat(SCSIZE nC, SCSIZE nR)
 {
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetNewMat" );
-    ScMatrixRef pMat = new ScMatrix( nC, nR);
+    ScMatrixRef pMat = new ScMatrix(nC, nR, 0.0);
     pMat->SetErrorInterpreter( this);
     // A temporary matrix is mutable and ScMatrix::CloneIfConst() returns the
     // very matrix.
@@ -556,18 +556,17 @@ ScMatrixRef ScInterpreter::GetMatrix()
             }
             if (pToken->GetType() == svDouble)
             {
-                pMat = new ScMatrix(1, 1);
+                pMat = new ScMatrix(1, 1, 0.0);
                 pMat->PutDouble(pToken->GetDouble(), 0, 0);
             }
             else if (pToken->GetType() == svString)
             {
-                pMat = new ScMatrix(1, 1);
+                pMat = new ScMatrix(1, 1, 0.0);
                 pMat->PutString(pToken->GetString(), 0, 0);
             }
             else
             {
                 pMat = new ScMatrix(1, 1);
-                pMat->PutEmpty(0, 0);
             }
         }
         break;
diff --git a/sc/source/core/tool/rangeseq.cxx b/sc/source/core/tool/rangeseq.cxx
index 9285051..ff35018 100644
--- a/sc/source/core/tool/rangeseq.cxx
+++ b/sc/source/core/tool/rangeseq.cxx
@@ -410,7 +410,7 @@ ScMatrixRef ScSequenceToMatrix::CreateMixedMatrix( const com::sun::star::uno::An
             rtl::OUString aUStr;
             xMatrix = new ScMatrix(
                     static_cast<SCSIZE>(nMaxColCount),
-                    static_cast<SCSIZE>(nRowCount) );
+                    static_cast<SCSIZE>(nRowCount), 0.0);
             SCSIZE nCols, nRows;
             xMatrix->GetDimensions( nCols, nRows);
             if (nCols != static_cast<SCSIZE>(nMaxColCount) || nRows != static_cast<SCSIZE>(nRowCount))
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 1d7f2a1..00e17c0 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -1492,7 +1492,7 @@ FormulaToken* ScTokenArray::MergeArray( )
         return NULL;
 
     int nSign = 1;
-    ScMatrix* pArray = new ScMatrix( nCol, nRow );
+    ScMatrix* pArray = new ScMatrix(nCol, nRow, 0.0);
     for ( i = nStart, nCol = 0, nRow = 0 ; i < nLen ; i++ )
     {
         t = pCode[i];
diff --git a/sc/source/filter/excel/xihelper.cxx b/sc/source/filter/excel/xihelper.cxx
index 034a727..edac049 100644
--- a/sc/source/filter/excel/xihelper.cxx
+++ b/sc/source/filter/excel/xihelper.cxx
@@ -861,7 +861,7 @@ ScMatrixRef XclImpCachedMatrix::CreateScMatrix() const
     OSL_ENSURE( mnScCols * mnScRows == maValueList.size(), "XclImpCachedMatrix::CreateScMatrix - element count mismatch" );
     if( mnScCols && mnScRows && static_cast< sal_uLong >( mnScCols * mnScRows ) <= maValueList.size() )
     {
-        xScMatrix = new ScMatrix( mnScCols, mnScRows );
+        xScMatrix = new ScMatrix(mnScCols, mnScRows, 0.0);
         XclImpValueList::const_iterator itValue = maValueList.begin();
         for( SCSIZE nScRow = 0; nScRow < mnScRows; ++nScRow )
         {
diff --git a/sc/source/filter/xml/XMLDDELinksContext.cxx b/sc/source/filter/xml/XMLDDELinksContext.cxx
index 54eafd0..4c3c496 100644
--- a/sc/source/filter/xml/XMLDDELinksContext.cxx
+++ b/sc/source/filter/xml/XMLDDELinksContext.cxx
@@ -169,7 +169,7 @@ void ScXMLDDELinkContext::EndElement()
             OSL_ENSURE( static_cast<size_t>(nColumns * nRows) == aDDELinkTable.size(),
                     "ScXMLDDELinkContext::EndElement: adapted matrix dimension doesn't match either");
         }
-        ScMatrixRef pMatrix = new ScMatrix( static_cast<SCSIZE>(nColumns), static_cast<SCSIZE>(nRows) );
+        ScMatrixRef pMatrix = new ScMatrix(static_cast<SCSIZE>(nColumns), static_cast<SCSIZE>(nRows), 0.0);
         sal_Int32 nCol(0);
         sal_Int32 nRow(-1);
         sal_Int32 nIndex(0);
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index 101a8ac..e1e18c1 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -1465,9 +1465,6 @@ static ScTokenArray* lcl_fillEmptyMatrix(const ScRange& rRange)
     SCSIZE nC = static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1);
     SCSIZE nR = static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1);
     ScMatrixRef xMat = new ScMatrix(nC, nR);
-    for (SCSIZE i = 0; i < nC; ++i)
-        for (SCSIZE j = 0; j < nR; ++j)
-            xMat->PutEmpty(i, j);
 
     ScMatrixToken aToken(xMat);
     SAL_WNODEPRECATED_DECLARATIONS_PUSH
commit c31905c88ca6160a2c12565e036f5aa02a5be086
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Jul 16 23:05:50 2012 -0400

    Initial cut on matrix backend swapping. Still lots of things to fix.
    
    Change-Id: I5262899171029772f53dccc9aea666c4b83aef36

diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index 9657540..d6d3e15 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -169,12 +169,16 @@ public:
     /// The maximum number of elements a matrix may have at runtime.
     inline static size_t GetElementsMax()
     {
+        // TODO: Fix me.
+        return 0x08000000;
+#if 0
         // Roughly 125MB in total, divided by 8+1 per element => 14M elements.
         const size_t nMemMax = 0x08000000 / (sizeof(ScMatrixValue) + sizeof(ScMatValType));
         // With MAXROWCOUNT==65536 and 128 columns => 8M elements ~72MB.
         const size_t nArbitraryLimit = (size_t)MAXROWCOUNT * 128;
         // Stuffed with a million rows would limit this to 14 columns.
         return nMemMax < nArbitraryLimit ? nMemMax : nArbitraryLimit;
+#endif
     }
 
     /// Value or boolean.
@@ -215,11 +219,11 @@ public:
         return (nType & SC_MATVAL_NONVALUE) == SC_MATVAL_EMPTYPATH;
     }
 
-    ScMatrix( SCSIZE nC, SCSIZE nR, DensityType eType = FILLED_ZERO);
+    ScMatrix(SCSIZE nC, SCSIZE nR);
+    ScMatrix(SCSIZE nC, SCSIZE nR, double fInitVal);
 
     /** Clone the matrix. */
     ScMatrix* Clone() const;
-    ScMatrix* Clone( DensityType eType) const;
 
     /** Clone the matrix if mbCloneIfConst (immutable) is set, otherwise
         return _this_ matrix, to be assigned to a ScMatrixRef. */
@@ -236,7 +240,7 @@ public:
 
     /** Clone the matrix and extend it to the new size. nNewCols and nNewRows
         MUST be at least of the size of the original matrix. */
-    ScMatrix* CloneAndExtend( SCSIZE nNewCols, SCSIZE nNewRows, DensityType eType) const;
+    ScMatrix* CloneAndExtend(SCSIZE nNewCols, SCSIZE nNewRows) const;
 
     inline void IncRef() const
     {
@@ -249,7 +253,6 @@ public:
             delete this;
     }
 
-    DensityType GetDensityType() const;
     void SetErrorInterpreter( ScInterpreter* p);
     void GetDimensions( SCSIZE& rC, SCSIZE& rR) const;
     SCSIZE GetElementCount() const;
@@ -303,9 +306,9 @@ public:
     double GetDouble( SCSIZE nIndex) const;
 
     /// @return empty string if empty or empty path, else string content.
-    const ::rtl::OUString& GetString( SCSIZE nC, SCSIZE nR) const;
+    rtl::OUString GetString( SCSIZE nC, SCSIZE nR) const;
     /// @return empty string if empty or empty path, else string content.
-    const ::rtl::OUString& GetString( SCSIZE nIndex) const;
+    rtl::OUString GetString( SCSIZE nIndex) const;
 
     /** @returns the matrix element's string if one is present, otherwise the
         numerical value formatted as string, or in case of an error the error
diff --git a/sc/source/core/inc/jumpmatrix.hxx b/sc/source/core/inc/jumpmatrix.hxx
index be2719c..27dfecd 100644
--- a/sc/source/core/inc/jumpmatrix.hxx
+++ b/sc/source/core/inc/jumpmatrix.hxx
@@ -195,7 +195,7 @@ public:
                                     {
                                         if ( nNewCols > nResMatCols || nNewRows > nResMatRows )
                                         {
-                                            pMat = pMat->CloneAndExtend( nNewCols, nNewRows, pMat->GetDensityType() );
+                                            pMat = pMat->CloneAndExtend(nNewCols, nNewRows);
                                             if ( nResMatCols < nNewCols )
                                             {
                                                 pMat->FillDouble( CreateDoubleError(
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 15c1c89..4b453b2 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -4621,7 +4621,7 @@ public:
         return mbColVec ? mrMat.GetDouble(0, i) : mrMat.GetDouble(i, 0);
     }
 
-    const rtl::OUString& GetString(SCSIZE i) const
+    rtl::OUString GetString(SCSIZE i) const
     {
         return mbColVec ? mrMat.GetString(0, i) : mrMat.GetString(i, 0);
     }
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 0aa891a..ee6e658 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -38,21 +38,263 @@
 
 #include <math.h>
 
-#define MDDS_HASH_CONTAINER_BOOST 1
-#include <mdds/mixed_type_matrix.hpp>
+#include <mdds/multi_type_matrix.hpp>
+#include <mdds/multi_type_vector_types.hpp>
+#include <mdds/multi_type_vector_trait.hpp>
 
 using ::std::pair;
 using ::std::for_each;
 using ::std::count_if;
 using ::std::advance;
 using ::std::unary_function;
-using ::mdds::matrix_element_t;
+
+const mdds::mtv::element_t element_type_custom_string = mdds::mtv::element_type_user_start;
+typedef mdds::mtv::default_element_block<element_type_custom_string, rtl::OUString> custom_string_block;
+
+namespace rtl {
+
+mdds::mtv::element_t mdds_mtv_get_element_type(const OUString&)
+{
+    return element_type_custom_string;
+}
+
+void mdds_mtv_set_value(mdds::mtv::base_element_block& block, size_t pos, const OUString& val)
+{
+    custom_string_block::set_value(block, pos, val);
+}
+
+void mdds_mtv_get_value(const mdds::mtv::base_element_block& block, size_t pos, OUString& val)
+{
+    custom_string_block::get_value(block, pos, val);
+}
+
+template<typename _Iter>
+void mdds_mtv_set_values(
+    mdds::mtv::base_element_block& block, size_t pos, const OUString&, const _Iter& it_begin, const _Iter& it_end)
+{
+    custom_string_block::set_values(block, pos, it_begin, it_end);
+}
+
+void mdds_mtv_append_value(mdds::mtv::base_element_block& block, const OUString& val)
+{
+    custom_string_block::append_value(block, val);
+}
+
+void mdds_mtv_prepend_value(mdds::mtv::base_element_block& block, const OUString& val)
+{
+    custom_string_block::prepend_value(block, val);
+}
+
+template<typename _Iter>
+void mdds_mtv_prepend_values(mdds::mtv::base_element_block& block, const OUString&, const _Iter& it_begin, const _Iter& it_end)
+{
+    custom_string_block::prepend_values(block, it_begin, it_end);
+}
+
+template<typename _Iter>
+void mdds_mtv_append_values(mdds::mtv::base_element_block& block, const OUString&, const _Iter& it_begin, const _Iter& it_end)
+{
+    custom_string_block::append_values(block, it_begin, it_end);
+}
+
+template<typename _Iter>
+void mdds_mtv_assign_values(mdds::mtv::base_element_block& dest, const OUString&, const _Iter& it_begin, const _Iter& it_end)
+{
+    custom_string_block::assign_values(dest, it_begin, it_end);
+}
+
+void mdds_mtv_get_empty_value(OUString& val)
+{
+    val = OUString();
+}
+
+template<typename _Iter>
+void mdds_mtv_insert_values(
+    mdds::mtv::base_element_block& block, size_t pos, const OUString&, const _Iter& it_begin, const _Iter& it_end)
+{
+    custom_string_block::insert_values(block, pos, it_begin, it_end);
+}
+
+mdds::mtv::base_element_block* mdds_mtv_create_new_block(size_t init_size, const OUString& val)
+{
+    return custom_string_block::create_block_with_value(init_size, val);
+}
+
+}
+
+struct custom_string_trait
+{
+    typedef OUString string_type;
+    typedef custom_string_block string_element_block;
+
+    static const mdds::mtv::element_t string_type_identifier = element_type_custom_string;
+
+    struct element_block_func
+    {
+        static mdds::mtv::base_element_block* create_new_block(
+            mdds::mtv::element_t type, size_t init_size)
+        {
+            switch (type)
+            {
+                case element_type_custom_string:
+                    return string_element_block::create_block(init_size);
+                default:
+                    return mdds::mtv::element_block_func::create_new_block(type, init_size);
+            }
+        }
+
+        static mdds::mtv::base_element_block* clone_block(const mdds::mtv::base_element_block& block)
+        {
+            switch (mdds::mtv::get_block_type(block))
+            {
+                case element_type_custom_string:
+                    return string_element_block::clone_block(block);
+                default:
+                    return mdds::mtv::element_block_func::clone_block(block);
+            }
+        }
+
+        static void delete_block(mdds::mtv::base_element_block* p)
+        {
+            if (!p)
+                return;
+
+            switch (mdds::mtv::get_block_type(*p))
+            {
+                case element_type_custom_string:
+                    string_element_block::delete_block(p);
+                break;
+                default:
+                    mdds::mtv::element_block_func::delete_block(p);
+            }
+        }
+
+        static void resize_block(mdds::mtv::base_element_block& block, size_t new_size)
+        {
+            switch (mdds::mtv::get_block_type(block))
+            {
+                case element_type_custom_string:
+                    string_element_block::resize_block(block, new_size);
+                break;
+                default:
+                    mdds::mtv::element_block_func::resize_block(block, new_size);
+            }
+        }
+
+        static void print_block(const mdds::mtv::base_element_block& block)
+        {
+            switch (mdds::mtv::get_block_type(block))
+            {
+                case element_type_custom_string:
+                    string_element_block::print_block(block);
+                break;
+                default:
+                    mdds::mtv::element_block_func::print_block(block);
+            }
+        }
+
+        static void erase(mdds::mtv::base_element_block& block, size_t pos)
+        {
+            switch (mdds::mtv::get_block_type(block))
+            {
+                case element_type_custom_string:
+                    string_element_block::erase_block(block, pos);
+                break;
+                default:
+                    mdds::mtv::element_block_func::erase(block, pos);
+            }
+        }
+
+        static void erase(mdds::mtv::base_element_block& block, size_t pos, size_t size)
+        {
+            switch (mdds::mtv::get_block_type(block))
+            {
+                case element_type_custom_string:
+                    string_element_block::erase_block(block, pos, size);
+                break;
+                default:
+                    mdds::mtv::element_block_func::erase(block, pos, size);
+            }
+        }
+
+        static void append_values_from_block(
+            mdds::mtv::base_element_block& dest, const mdds::mtv::base_element_block& src)
+        {
+            switch (mdds::mtv::get_block_type(dest))
+            {
+                case element_type_custom_string:
+                    string_element_block::append_values_from_block(dest, src);
+                break;
+                default:
+                    mdds::mtv::element_block_func::append_values_from_block(dest, src);
+            }
+        }
+
+        static void append_values_from_block(
+            mdds::mtv::base_element_block& dest, const mdds::mtv::base_element_block& src,
+            size_t begin_pos, size_t len)
+        {
+            switch (mdds::mtv::get_block_type(dest))
+            {
+                case element_type_custom_string:
+                    string_element_block::append_values_from_block(dest, src, begin_pos, len);
+                break;
+                default:
+                    mdds::mtv::element_block_func::append_values_from_block(dest, src, begin_pos, len);
+            }
+        }
+
+        static void assign_values_from_block(
+            mdds::mtv::base_element_block& dest, const mdds::mtv::base_element_block& src,
+            size_t begin_pos, size_t len)
+        {
+            switch (mdds::mtv::get_block_type(dest))
+            {
+                case element_type_custom_string:
+                    string_element_block::assign_values_from_block(dest, src, begin_pos, len);
+                break;
+                default:
+                    mdds::mtv::element_block_func::assign_values_from_block(dest, src, begin_pos, len);
+            }
+        }
+
+        static bool equal_block(
+            const mdds::mtv::base_element_block& left, const mdds::mtv::base_element_block& right)
+        {
+            if (mdds::mtv::get_block_type(left) == element_type_custom_string)
+            {
+                if (mdds::mtv::get_block_type(right) != element_type_custom_string)
+                    return false;
+
+                return string_element_block::get(left) == string_element_block::get(right);
+            }
+            else if (mdds::mtv::get_block_type(right) == element_type_custom_string)
+                return false;
+
+            return mdds::mtv::element_block_func::equal_block(left, right);
+        }
+
+        static void overwrite_values(mdds::mtv::base_element_block& block, size_t pos, size_t len)
+        {
+            switch (mdds::mtv::get_block_type(block))
+            {
+                case element_type_custom_string:
+                    // Do nothing.  The client code manages the life cycle of these cells.
+                break;
+                default:
+                    mdds::mtv::element_block_func::overwrite_values(block, pos, len);
+            }
+        }
+    };
+};
+
 
 // ============================================================================
 
 namespace {
 
-typedef ::mdds::mixed_type_matrix< ::rtl::OUString, sal_uInt8> MatrixImplType;
+typedef mdds::multi_type_matrix<custom_string_trait> MatrixImplType;
+//typedef ::mdds::mixed_type_matrix< ::rtl::OUString, sal_uInt8> MatrixImplType;
 
 struct ElemEqual : public unary_function<double, bool>
 {
@@ -105,14 +347,14 @@ struct ElemLessEqual : public unary_function<double, bool>
 template<typename _Comp>
 void compareMatrix(MatrixImplType& rMat)
 {
-    pair<size_t,size_t> aDim = rMat.size();
+    MatrixImplType::size_pair_type aDim = rMat.size();
     _Comp aComp;
-    for (size_t i = 0; i < aDim.first; ++i)
+    for (size_t i = 0; i < aDim.row; ++i)
     {
-        for (size_t j = 0; j < aDim.second; ++j)
+        for (size_t j = 0; j < aDim.column; ++j)
         {
-            matrix_element_t eType = rMat.get_type(i, j);
-            if (eType != mdds::element_numeric && eType != mdds::element_boolean)
+            mdds::mtm::element_t eType = rMat.get_type(i, j);
+            if (eType != mdds::mtm::element_numeric && eType != mdds::mtm::element_boolean)
                 // must be of numeric type (boolean can be numeric).
                 continue;
 
@@ -120,31 +362,13 @@ void compareMatrix(MatrixImplType& rMat)
             if (!::rtl::math::isFinite(fVal))
                 continue;
 
-            rMat.set_boolean(i, j, aComp(fVal));
+            bool b = aComp(fVal);
+            rMat.set(i, j, b);
         }
     }
 }
 
-::mdds::matrix_density_t toMddsDensityType(ScMatrix::DensityType eType)
-{
-    switch (eType)
-    {
-        case ScMatrix::FILLED_EMPTY:
-            return mdds::matrix_density_filled_empty;
-        case ScMatrix::FILLED_ZERO:
-            return mdds::matrix_density_filled_zero;
-        case ScMatrix::SPARSE_EMPTY:
-            return mdds::matrix_density_sparse_empty;
-        case ScMatrix::SPARSE_ZERO:
-            return mdds::matrix_density_sparse_zero;
-        default:
-            ;
-    }
-
-    // default density type
-    return mdds::matrix_density_filled_zero;
-}
-
+#if 0
 /**
  * Return a numeric value from a matrix element no matter what its type is.
  */
@@ -161,13 +385,14 @@ double getNumericValue(const MatrixImplType::element& elem)
     }
     return 0.0;
 }
+#endif
 
 }
 
 class ScMatrixImpl
 {
     MatrixImplType maMat;
-    ScMatrix::DensityType meType;
+    MatrixImplType maMatFlag;
     ScInterpreter* pErrorInterpreter;
     bool            mbCloneIfConst; // Whether the matrix is cloned with a CloneIfConst() call.
     MatrixImplType::size_pair_type  maCachedSize;
@@ -175,14 +400,14 @@ class ScMatrixImpl
     ScMatrixImpl();
     ScMatrixImpl(const ScMatrixImpl&);
 public:
-    ScMatrixImpl(SCSIZE nC, SCSIZE nR, ScMatrix::DensityType eType);
+    ScMatrixImpl(SCSIZE nC, SCSIZE nR);
+    ScMatrixImpl(SCSIZE nC, SCSIZE nR, double fInitVal);
     ~ScMatrixImpl();
 
     void Clear();
     void SetImmutable(bool bVal);
     bool IsImmutable() const;
     void Resize(SCSIZE nC, SCSIZE nR);
-    ScMatrix::DensityType GetDensityType() const;
     void SetErrorInterpreter( ScInterpreter* p);
     ScInterpreter* GetErrorInterpreter() const { return pErrorInterpreter; }
 
@@ -204,9 +429,9 @@ public:
     sal_uInt16 GetError( SCSIZE nC, SCSIZE nR) const;
     double GetDouble(SCSIZE nC, SCSIZE nR) const;
     double GetDouble( SCSIZE nIndex) const;
-    const ::rtl::OUString& GetString(SCSIZE nC, SCSIZE nR) const;
-    const ::rtl::OUString& GetString( SCSIZE nIndex) const;
-    ::rtl::OUString GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const;
+    rtl::OUString GetString(SCSIZE nC, SCSIZE nR) const;
+    rtl::OUString GetString( SCSIZE nIndex) const;
+    rtl::OUString GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const;
     ScMatrixValue Get(SCSIZE nC, SCSIZE nR) const;
     bool IsString( SCSIZE nIndex ) const;
     bool IsString( SCSIZE nC, SCSIZE nR ) const;
@@ -238,14 +463,11 @@ private:
     void CalcPosition(SCSIZE nIndex, SCSIZE& rC, SCSIZE& rR) const;
 };
 
-ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR, ScMatrix::DensityType eType) :
-    maMat(nR, nC, toMddsDensityType(eType)),
-    meType(eType),
-    pErrorInterpreter(NULL),
-    mbCloneIfConst(true)
-{
-    maCachedSize = maMat.size();
-}
+ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR) :
+    maMat(nR, nC), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
+
+ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR, double fInitVal) :
+    maMat(nR, nC, fInitVal), pErrorInterpreter(NULL), mbCloneIfConst(true) {}
 
 ScMatrixImpl::~ScMatrixImpl()
 {
@@ -255,7 +477,6 @@ ScMatrixImpl::~ScMatrixImpl()
 void ScMatrixImpl::Clear()
 {
     maMat.clear();
-    maCachedSize = maMat.size();
 }
 
 void ScMatrixImpl::SetImmutable(bool bVal)
@@ -271,12 +492,6 @@ bool ScMatrixImpl::IsImmutable() const
 void ScMatrixImpl::Resize(SCSIZE nC, SCSIZE nR)
 {
     maMat.resize(nR, nC);
-    maCachedSize = maMat.size();
-}
-
-ScMatrix::DensityType ScMatrixImpl::GetDensityType() const
-{
-    return meType;
 }
 
 void ScMatrixImpl::SetErrorInterpreter( ScInterpreter* p)
@@ -286,35 +501,39 @@ void ScMatrixImpl::SetErrorInterpreter( ScInterpreter* p)
 
 void ScMatrixImpl::GetDimensions( SCSIZE& rC, SCSIZE& rR) const
 {
-    rR = maCachedSize.first;
-    rC = maCachedSize.second;
+    MatrixImplType::size_pair_type aSize = maMat.size();
+    rR = aSize.row;
+    rC = aSize.column;
 }
 
 SCSIZE ScMatrixImpl::GetElementCount() const
 {
-    return maCachedSize.first * maCachedSize.second;
+    MatrixImplType::size_pair_type aSize = maMat.size();
+    return aSize.row * aSize.column;
 }
 
 bool ScMatrixImpl::ValidColRow( SCSIZE nC, SCSIZE nR) const
 {
-    return nR < maCachedSize.first && nC < maCachedSize.second;
+    MatrixImplType::size_pair_type aSize = maMat.size();
+    return nR < aSize.row && nC < aSize.column;
 }
 
 bool ScMatrixImpl::ValidColRowReplicated( SCSIZE & rC, SCSIZE & rR ) const
 {
-    if (maCachedSize.second == 1 && maCachedSize.first == 1)
+    MatrixImplType::size_pair_type aSize = maMat.size();
+    if (aSize.column == 1 && aSize.row == 1)
     {
         rC = 0;
         rR = 0;
         return true;
     }
-    else if (maCachedSize.second == 1 && rR < maCachedSize.first)
+    else if (aSize.column == 1 && rR < aSize.row)
     {
         // single column matrix.
         rC = 0;
         return true;
     }
-    else if (maCachedSize.first == 1 && rC < maCachedSize.second)
+    else if (aSize.row == 1 && rC < aSize.column)
     {
         // single row matrix.
         rR = 0;
@@ -337,7 +556,7 @@ void ScMatrixImpl::SetErrorAtInterpreter( sal_uInt16 nError ) const
 void ScMatrixImpl::PutDouble(double fVal, SCSIZE nC, SCSIZE nR)
 {
     if (ValidColRow( nC, nR))
-        maMat.set_numeric(nR, nC, fVal);
+        maMat.set(nR, nC, fVal);
     else
     {
         OSL_FAIL("ScMatrixImpl::PutDouble: dimension error");
@@ -354,7 +573,7 @@ void ScMatrixImpl::PutDouble( double fVal, SCSIZE nIndex)
 void ScMatrixImpl::PutString(const ::rtl::OUString& rStr, SCSIZE nC, SCSIZE nR)
 {
     if (ValidColRow( nC, nR))
-        maMat.set_string(nR, nC, new ::rtl::OUString(rStr));
+        maMat.set(nR, nC, rtl::OUString(rStr));
     else
     {
         OSL_FAIL("ScMatrixImpl::PutString: dimension error");
@@ -373,7 +592,7 @@ void ScMatrixImpl::PutEmpty(SCSIZE nC, SCSIZE nR)
     if (ValidColRow( nC, nR))
     {
         maMat.set_empty(nR, nC);
-        maMat.clear_flag(nR, nC); // zero flag to indicate that this is 'empty', not 'empty path'.
+        maMatFlag.set(nR, nC, false); // zero flag to indicate that this is 'empty', not 'empty path'.
     }
     else
     {
@@ -386,7 +605,7 @@ void ScMatrixImpl::PutEmptyPath(SCSIZE nC, SCSIZE nR)
     if (ValidColRow( nC, nR))
     {
         maMat.set_empty(nR, nC);
-        maMat.set_flag(nR, nC, 1); // non-zero flag to indicate empty 'path'.
+        maMatFlag.set(nR, nC, true); // non-zero flag to indicate empty 'path'.
     }
     else
     {
@@ -396,13 +615,13 @@ void ScMatrixImpl::PutEmptyPath(SCSIZE nC, SCSIZE nR)
 
 void ScMatrixImpl::PutError( sal_uInt16 nErrorCode, SCSIZE nC, SCSIZE nR )
 {
-    maMat.set_numeric(nR, nC, CreateDoubleError(nErrorCode));
+    maMat.set(nR, nC, CreateDoubleError(nErrorCode));
 }
 
 void ScMatrixImpl::PutBoolean(bool bVal, SCSIZE nC, SCSIZE nR)
 {
     if (ValidColRow( nC, nR))
-        maMat.set_boolean(nR, nC, bVal);

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list