[Libreoffice-commits] core.git: Branch 'private/kohei/calc-shared-string' - 8 commits - sc/inc sc/Library_sc.mk sc/qa sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Thu Oct 17 21:35:12 PDT 2013


 sc/Library_sc.mk                 |    1 
 sc/inc/compare.hxx               |   74 ++++
 sc/inc/scmatrix.hxx              |   70 ++++
 sc/qa/unit/ucalc.cxx             |    2 
 sc/source/core/inc/interpre.hxx  |   12 
 sc/source/core/tool/compare.cxx  |  198 ++++++++++++
 sc/source/core/tool/interpr1.cxx |  272 +---------------
 sc/source/core/tool/scmatrix.cxx |  636 +++++++++++++++++++++++++++++++++++----
 8 files changed, 951 insertions(+), 314 deletions(-)

New commits:
commit fd4c962ceadb7e77adc0160a20f5c6a823887bb1
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Oct 18 00:22:11 2013 -0400

    Faster way to add two result matrices.
    
    Change-Id: I347aec7de10a943d7f91c468cd6e393f980e53b6

diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index 8317b85..5e9800e 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -167,7 +167,7 @@ public:
     };
 
     typedef boost::interprocess::unique_ptr<Pos, PosDeleter> PosRef;
-    typedef boost::interprocess::unique_ptr<ConstPos, PosDeleter> ConstPosRef;
+    typedef boost::interprocess::unique_ptr<ConstPos, ConstPosDeleter> ConstPosRef;
 
     /// The maximum number of elements a matrix may have at runtime.
     inline static size_t GetElementsMax()
@@ -407,6 +407,8 @@ public:
     void GetDoubleArray( std::vector<double>& rArray ) const;
     void MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const;
 
+    ScMatrix& operator+= ( const ScMatrix& r );
+
 #if DEBUG_MATRIX
     void Dump() const;
 #endif
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index dc6bd5c..7515c0c 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -5470,19 +5470,9 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                         SetError( errIllegalParameter);
                     }
 
-                    for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
-                    {
-                        for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
-                        {
-                            if (pResultMatrix->IsValue( nCol, nRow) &&
-                                    pResultMatrix->GetDouble( nCol, nRow))
-                            {
-                                SCSIZE nC = nCol + nColDiff;
-                                SCSIZE nR = nRow + nRowDiff;
-                                pResMat->PutDouble(pResMat->GetDouble(nC, nR)+1.0, nC, nR);
-                            }
-                        }
-                    }
+                    // query and result matrices have same geometry, and the
+                    // result matrix is filled with boolean values.
+                    *pResMat += *pResultMatrix;
                 }
                 else
                 {
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 5d8cc9a2..29dcda7 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -304,6 +304,7 @@ public:
 
     void GetDoubleArray( std::vector<double>& rArray ) const;
     void MergeDoubleArray( std::vector<double>& rArray, ScMatrix::Op eOp ) const;
+    void AddValues( const ScMatrixImpl& rMat );
 
 #if DEBUG_MATRIX
     void Dump() const;
@@ -1696,6 +1697,61 @@ void ScMatrixImpl::MergeDoubleArray( std::vector<double>& rArray, ScMatrix::Op e
     }
 }
 
+void ScMatrixImpl::AddValues( const ScMatrixImpl& rMat )
+{
+    const MatrixImplType& rOther = rMat.maMat;
+    MatrixImplType::size_pair_type aSize = maMat.size();
+    if (aSize != rOther.size())
+        // Geometry must match.
+        return;
+
+    // For now, we only add two matricies if and only if 1) the receiving
+    // matrix consists only of one numeric block, and 2) the other matrix
+    // consists of either one numeric block or one boolean block.  In the
+    // future, we may want to be more flexible support matricies that consist
+    // of multiple blocks.
+
+    MatrixImplType::position_type aPos1 = maMat.position(0, 0);
+    MatrixImplType::const_position_type aPos2 = rOther.position(0, 0);
+    if (MatrixImplType::to_mtm_type(aPos1.first->type) != mdds::mtm::element_numeric)
+        return;
+
+    if (aPos1.first->size != aPos2.first->size)
+        return;
+
+    if (aPos1.first->size != aSize.row * aSize.column)
+        return;
+
+    MatrixImplType::numeric_block_type::iterator it =
+        MatrixImplType::numeric_block_type::begin(*aPos1.first->data);
+    MatrixImplType::numeric_block_type::iterator itEnd =
+        MatrixImplType::numeric_block_type::end(*aPos1.first->data);
+
+    switch (MatrixImplType::to_mtm_type(aPos2.first->type))
+    {
+        case mdds::mtm::element_boolean:
+        {
+            MatrixImplType::boolean_block_type::iterator it2 =
+                MatrixImplType::boolean_block_type::begin(*aPos2.first->data);
+
+            for (; it != itEnd; ++it, ++it2)
+                *it += *it2;
+        }
+        break;
+        case mdds::mtm::element_numeric:
+        {
+            MatrixImplType::numeric_block_type::iterator it2 =
+                MatrixImplType::numeric_block_type::begin(*aPos2.first->data);
+
+            for (; it != itEnd; ++it, ++it2)
+                *it += *it2;
+        }
+        break;
+        default:
+            ;
+    }
+}
+
 #if DEBUG_MATRIX
 void ScMatrixImpl::Dump() const
 {
@@ -2193,6 +2249,12 @@ void ScMatrix::MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const
     pImpl->MergeDoubleArray(rArray, eOp);
 }
 
+ScMatrix& ScMatrix::operator+= ( const ScMatrix& r )
+{
+    pImpl->AddValues(*r.pImpl);
+    return *this;
+}
+
 #if DEBUG_MATRIX
 void ScMatrix::Dump() const
 {
commit e021c158a0c25fd35dc5df72d86e619771daf1e9
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Oct 17 22:55:20 2013 -0400

    No need to fill zeros here. The matrix is initialized with zeros.
    
    Change-Id: I842819ed5ee040d4c65c3676ea35707d4087602a

diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index df77eef..dc6bd5c 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -5425,11 +5425,9 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                     SCSIZE nResC, nResR;
                     nResC = nCol2 - nCol1 + 1;
                     nResR = nRow2 - nRow1 + 1;
-                    pResMat = GetNewMat(nResC, nResR);
+                    pResMat = GetNewMat(nResC, nResR, false);
                     if (!pResMat)
                         SetError( errIllegalParameter);
-                    else
-                        pResMat->FillDouble( 0.0, 0, 0, nResC-1, nResR-1);
                 }
 
                 ScQueryParam rParam;
commit e1678f258d76ea2a026a57e7c8b346097bd658fe
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Oct 17 22:21:01 2013 -0400

    Re-write CompareEqual etc. to make it run faster.
    
    Change-Id: I6efeff7c97695cab060319f20fae8673286a6c0a

diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 96ed001..5d8cc9a2 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -136,33 +136,67 @@ struct ElemLessEqualZero : public unary_function<double, bool>
 };
 
 template<typename _Comp>
-void compareMatrix(MatrixImplType& rMat)
+class CompareMatrixElemFunc : std::unary_function<MatrixImplType::element_block_node_type, void>
 {
-    MatrixImplType::size_pair_type aDim = rMat.size();
-    MatrixImplType aNewMat(aDim.row, aDim.column, false); // initialize with boolean block.  faster this way.
+    static _Comp maComp;
 
-    _Comp aComp;
-    for (size_t i = 0; i < aDim.row; ++i)
+    MatrixImplType maNewMat;
+    std::deque<bool> maNewMatValues;
+public:
+    CompareMatrixElemFunc( size_t nRow, size_t nCol ) :
+        maNewMat(nRow, nCol, false) {}
+
+    void operator() (const MatrixImplType::element_block_node_type& node)
     {
-        for (size_t j = 0; j < aDim.column; ++j)
+        switch (node.type)
         {
-            MatrixImplType::const_position_type aPos = rMat.position(i, j);
-            mdds::mtm::element_t eType = rMat.get_type(aPos);
-            if (eType != mdds::mtm::element_numeric && eType != mdds::mtm::element_boolean)
-                // must be of numeric type (boolean can be numeric).
-                continue;
+            case mdds::mtm::element_numeric:
+            {
+                typedef MatrixImplType::numeric_block_type block_type;
 
-            double fVal = rMat.get_numeric(aPos);
-            if (!::rtl::math::isFinite(fVal))
-                /* FIXME: this silently skips an error instead of propagating it! */
-                continue;
+                block_type::const_iterator it = block_type::begin(*node.data);
+                block_type::const_iterator itEnd = block_type::end(*node.data);
+                for (; it != itEnd; ++it)
+                {
+                    double fVal = *it;
+                    if (!rtl::math::isFinite(fVal))
+                    {
+                        /* FIXME: this silently skips an error instead of propagating it! */
+                        maNewMatValues.push_back(false);
+                        continue;
+                    }
+
+                    maNewMatValues.push_back(maComp(fVal));
+                }
+            }
+            break;
+            case mdds::mtm::element_boolean:
+            {
+                typedef MatrixImplType::boolean_block_type block_type;
 
-            bool b = aComp(fVal);
-            aNewMat.set(i, j, b);
+                block_type::const_iterator it = block_type::begin(*node.data);
+                block_type::const_iterator itEnd = block_type::end(*node.data);
+                for (; it != itEnd; ++it)
+                {
+                    double fVal = *it ? 1.0 : 0.0;
+                    maNewMatValues.push_back(maComp(fVal));
+                }
+            }
+            break;
+            case mdds::mtm::element_string:
+            case mdds::mtm::element_empty:
+            default:
+                // Fill it with false.
+                maNewMatValues.resize(maNewMatValues.size() + node.size, false);
         }
     }
-    aNewMat.swap(rMat);
-}
+
+    void swap( MatrixImplType& rMat )
+    {
+        maNewMat.set(0, 0, maNewMatValues.begin(), maNewMatValues.end());
+        rMat.swap(maNewMat);
+    }
+};
 
 }
 
@@ -901,32 +935,50 @@ void ScMatrixImpl::FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2,
 
 void ScMatrixImpl::CompareEqual()
 {
-    compareMatrix<ElemEqualZero>(maMat);
+    MatrixImplType::size_pair_type aSize = maMat.size();
+    CompareMatrixElemFunc<ElemEqualZero> aFunc(aSize.row, aSize.column);
+    maMat.walk(aFunc);
+    aFunc.swap(maMat);
 }
 
 void ScMatrixImpl::CompareNotEqual()
 {
-    compareMatrix<ElemNotEqualZero>(maMat);
+    MatrixImplType::size_pair_type aSize = maMat.size();
+    CompareMatrixElemFunc<ElemNotEqualZero> aFunc(aSize.row, aSize.column);
+    maMat.walk(aFunc);
+    aFunc.swap(maMat);
 }
 
 void ScMatrixImpl::CompareLess()
 {
-    compareMatrix<ElemLessZero>(maMat);
+    MatrixImplType::size_pair_type aSize = maMat.size();
+    CompareMatrixElemFunc<ElemLessZero> aFunc(aSize.row, aSize.column);
+    maMat.walk(aFunc);
+    aFunc.swap(maMat);
 }
 
 void ScMatrixImpl::CompareGreater()
 {
-    compareMatrix<ElemGreaterZero>(maMat);
+    MatrixImplType::size_pair_type aSize = maMat.size();
+    CompareMatrixElemFunc<ElemGreaterZero> aFunc(aSize.row, aSize.column);
+    maMat.walk(aFunc);
+    aFunc.swap(maMat);
 }
 
 void ScMatrixImpl::CompareLessEqual()
 {
-    compareMatrix<ElemLessEqualZero>(maMat);
+    MatrixImplType::size_pair_type aSize = maMat.size();
+    CompareMatrixElemFunc<ElemLessEqualZero> aFunc(aSize.row, aSize.column);
+    maMat.walk(aFunc);
+    aFunc.swap(maMat);
 }
 
 void ScMatrixImpl::CompareGreaterEqual()
 {
-    compareMatrix<ElemGreaterEqualZero>(maMat);
+    MatrixImplType::size_pair_type aSize = maMat.size();
+    CompareMatrixElemFunc<ElemGreaterEqualZero> aFunc(aSize.row, aSize.column);
+    maMat.walk(aFunc);
+    aFunc.swap(maMat);
 }
 
 namespace {
@@ -1357,8 +1409,6 @@ public:
 
     void operator() (const MatrixImplType::element_block_node_type& node)
     {
-        using namespace mdds::mtv;
-
         switch (node.type)
         {
             case mdds::mtm::element_numeric:
commit 571a0f40e09cec9e52fd27226e7bb6e42bbbc3da
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Oct 17 21:44:35 2013 -0400

    A little cleanup. Derive block types from multi_type_matrix.
    
    Rather than directly using the blocks from mtv.
    
    Change-Id: I215e38ad406f8edc5d15c9f011dde649fce1d671

diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index fbf77cd..96ed001 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -1057,8 +1057,10 @@ public:
         {
             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);
+                typedef MatrixImplType::numeric_block_type block_type;
+
+                block_type::const_iterator it = block_type::begin(*node.data);
+                block_type::const_iterator itEnd = block_type::end(*node.data);
                 for (; it != itEnd; ++it)
                 {
                     if (mbFirst)
@@ -1074,8 +1076,10 @@ public:
             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);
+                typedef MatrixImplType::boolean_block_type block_type;
+
+                block_type::const_iterator it = block_type::begin(*node.data);
+                block_type::const_iterator itEnd = block_type::end(*node.data);
                 for (; it != itEnd; ++it)
                 {
                     if (mbFirst)
@@ -1177,8 +1181,10 @@ size_t WalkAndMatchElements<double>::compare(const MatrixImplType::element_block
     {
         case mdds::mtm::element_numeric:
         {
-            MatrixImplType::numeric_block_type::const_iterator it = MatrixImplType::numeric_block_type::begin(*node.data);
-            MatrixImplType::numeric_block_type::const_iterator itEnd = MatrixImplType::numeric_block_type::end(*node.data);
+            typedef MatrixImplType::numeric_block_type block_type;
+
+            block_type::const_iterator it = block_type::begin(*node.data);
+            block_type::const_iterator itEnd = block_type::end(*node.data);
             for (; it != itEnd; ++it, nCount++)
             {
                 if (*it == maMatchValue)
@@ -1190,8 +1196,10 @@ size_t WalkAndMatchElements<double>::compare(const MatrixImplType::element_block
         }
         case mdds::mtm::element_boolean:
         {
-            MatrixImplType::boolean_block_type::const_iterator it = MatrixImplType::boolean_block_type::begin(*node.data);
-            MatrixImplType::boolean_block_type::const_iterator itEnd = MatrixImplType::boolean_block_type::end(*node.data);
+            typedef MatrixImplType::boolean_block_type block_type;
+
+            block_type::const_iterator it = block_type::begin(*node.data);
+            block_type::const_iterator itEnd = block_type::end(*node.data);
             for (; it != itEnd; ++it, ++nCount)
             {
                 if (int(*it) == maMatchValue)
@@ -1218,8 +1226,10 @@ size_t WalkAndMatchElements<svl::SharedString>::compare(const MatrixImplType::el
     {
         case mdds::mtm::element_string:
         {
-            MatrixImplType::string_block_type::const_iterator it = MatrixImplType::string_block_type::begin(*node.data);
-            MatrixImplType::string_block_type::const_iterator itEnd = MatrixImplType::string_block_type::end(*node.data);
+            typedef MatrixImplType::string_block_type block_type;
+
+            block_type::const_iterator it = block_type::begin(*node.data);
+            block_type::const_iterator itEnd = block_type::end(*node.data);
             for (; it != itEnd; ++it, ++nCount)
             {
                 if (it->getDataIgnoreCase() == maMatchValue.getDataIgnoreCase())
@@ -1247,8 +1257,8 @@ struct MaxOp
     }
 
     static double boolValue(
-        mdds::mtv::boolean_element_block::const_iterator it,
-        mdds::mtv::boolean_element_block::const_iterator itEnd)
+        MatrixImplType::boolean_block_type::const_iterator it,
+        MatrixImplType::boolean_block_type::const_iterator itEnd)
     {
         // If the array has at least one true value, the maximum value is 1.
         it = std::find(it, itEnd, true);
@@ -1265,8 +1275,8 @@ struct MinOp
     }
 
     static double boolValue(
-        mdds::mtv::boolean_element_block::const_iterator it,
-        mdds::mtv::boolean_element_block::const_iterator itEnd)
+        MatrixImplType::boolean_block_type::const_iterator it,
+        MatrixImplType::boolean_block_type::const_iterator itEnd)
     {
         // If the array has at least one false value, the minimum value is 0.
         it = std::find(it, itEnd, false);
@@ -1288,22 +1298,25 @@ public:
 
     void operator() (const MatrixImplType::element_block_node_type& node)
     {
-        using namespace mdds::mtv;
 
         switch (node.type)
         {
             case mdds::mtm::element_numeric:
             {
-                numeric_element_block::const_iterator it = numeric_element_block::begin(*node.data);
-                numeric_element_block::const_iterator itEnd = numeric_element_block::end(*node.data);
+                typedef MatrixImplType::numeric_block_type block_type;
+
+                block_type::const_iterator it = block_type::begin(*node.data);
+                block_type::const_iterator itEnd = block_type::end(*node.data);
                 for (; it != itEnd; ++it)
                     mfVal = _Op::compare(mfVal, *it);
             }
             break;
             case mdds::mtm::element_boolean:
             {
-                boolean_element_block::const_iterator it = boolean_element_block::begin(*node.data);
-                boolean_element_block::const_iterator itEnd = boolean_element_block::end(*node.data);
+                typedef MatrixImplType::boolean_block_type block_type;
+
+                block_type::const_iterator it = block_type::begin(*node.data);
+                block_type::const_iterator itEnd = block_type::end(*node.data);
                 double fVal = _Op::boolValue(it, itEnd);
                 mfVal = _Op::compare(mfVal, fVal);
             }
commit f47a54943d7dea6d166fb7272441260f89fe9510
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Oct 17 21:03:12 2013 -0400

    Reduce the number of arguments. The first argument can go now.
    
    Change-Id: Id2b9ca7b6e24edc0da4735c01798ab580fba910d

diff --git a/sc/inc/compare.hxx b/sc/inc/compare.hxx
index 9ee2992..b4e4a50 100644
--- a/sc/inc/compare.hxx
+++ b/sc/inc/compare.hxx
@@ -62,7 +62,10 @@ private:
     CompareOptions& operator=( const CompareOptions & );
 };
 
-double CompareFunc( bool bIgnoreCase, const Compare& rComp, CompareOptions* pOptions = NULL );
+/** @param pOptions
+        NULL means case sensitivity document option is to be used!
+ */
+double CompareFunc( const Compare& rComp, CompareOptions* pOptions = NULL );
 
 }
 
diff --git a/sc/source/core/tool/compare.cxx b/sc/source/core/tool/compare.cxx
index ece2ff2..5f7dd12 100644
--- a/sc/source/core/tool/compare.cxx
+++ b/sc/source/core/tool/compare.cxx
@@ -38,10 +38,7 @@ CompareOptions::CompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bo
     // struct if needed.
 }
 
-/** @param pOptions
-        NULL means case sensitivity document option is to be used!
- */
-double CompareFunc( bool bIgnoreCase, const Compare& rComp, CompareOptions* pOptions )
+double CompareFunc( const Compare& rComp, CompareOptions* pOptions )
 {
     // Keep DoubleError if encountered
     // #i40539# if bEmpty is set, bVal/nVal are uninitialized
@@ -165,7 +162,7 @@ double CompareFunc( bool bIgnoreCase, const Compare& rComp, CompareOptions* pOpt
                 fRes = (double) ScGlobal::GetCaseCollator()->compareString(
                         *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
         }
-        else if (bIgnoreCase)
+        else if (rComp.mbIgnoreCase)
             fRes = (double) ScGlobal::GetCollator()->compareString(
                 *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
         else
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index f79a7b6..df77eef 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -875,7 +875,7 @@ double ScInterpreter::Compare()
     if( nGlobalError )
         return 0;
     nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
-    return sc::CompareFunc(pDok->GetDocOptions().IsIgnoreCase(), aComp);
+    return sc::CompareFunc(aComp);
 }
 
 
@@ -976,7 +976,7 @@ sc::RangeMatrix ScInterpreter::CompareMat( sc::CompareOptions* pOptions )
                                 aComp.bEmpty[i] = false;
                             }
                         }
-                        aRes.mpMat->PutDouble(sc::CompareFunc(pDok->GetDocOptions().IsIgnoreCase(), aComp, pOptions), j, k);
+                        aRes.mpMat->PutDouble(sc::CompareFunc(aComp, pOptions), j, k);
                     }
                     else
                         aRes.mpMat->PutString(mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE)), j, k);
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 8b45f00..fbf77cd 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -1332,7 +1332,7 @@ class CompareMatrixFunc : std::unary_function<MatrixImplType::element_block_type
 
     void compare()
     {
-        maResValues.push_back(sc::CompareFunc(mrComp.mbIgnoreCase, mrComp, mpOptions));
+        maResValues.push_back(sc::CompareFunc(mrComp, mpOptions));
     }
 
 public:
commit 4ea2fdd5c4144df680d7e7dcdd46cf5161c40532
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Oct 17 21:00:00 2013 -0400

    Move the compare-matrix code to ScMatrix, for much faster execution.
    
    Change-Id: I3c4f255469b48cfd6f132503ff695e347d8ae912

diff --git a/sc/inc/compare.hxx b/sc/inc/compare.hxx
index 307b531..9ee2992 100644
--- a/sc/inc/compare.hxx
+++ b/sc/inc/compare.hxx
@@ -35,7 +35,10 @@ struct Compare
     bool bVal[2];
     bool bEmpty[2];
 
-    Compare( OUString* p1, OUString* p2 )
+    bool mbIgnoreCase;
+
+    Compare( OUString* p1, OUString* p2 ) :
+        mbIgnoreCase(true)
     {
         pVal[0] = p1;
         pVal[1] = p2;
diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index edd8cbd..8317b85 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -36,6 +36,13 @@ class ScInterpreter;
 class SvNumberFormatter;
 class ScMatrixImpl;
 
+namespace sc {
+
+struct Compare;
+struct CompareOptions;
+
+}
+
 /**
  * Try NOT to use this struct.  This struct should go away in a hopefully
  * not so distant futture.
@@ -394,6 +401,9 @@ public:
     double GetMaxValue( bool bTextAsZero ) const;
     double GetMinValue( bool bTextAsZero ) const;
 
+    void CompareMatrix(
+        ScMatrix& rResMat, sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions = NULL ) const;
+
     void GetDoubleArray( std::vector<double>& rArray ) const;
     void MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const;
 
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index c60b871..f79a7b6 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -793,6 +793,7 @@ double ScInterpreter::Compare()
 {
     OUString aVal1, aVal2;
     sc::Compare aComp( &aVal1, &aVal2 );
+    aComp.mbIgnoreCase = pDok->GetDocOptions().IsIgnoreCase();
     for( short i = 1; i >= 0; i-- )
     {
         switch ( GetRawStackType() )
@@ -882,6 +883,7 @@ sc::RangeMatrix ScInterpreter::CompareMat( sc::CompareOptions* pOptions )
 {
     OUString aVal1, aVal2;
     sc::Compare aComp( &aVal1, &aVal2 );
+    aComp.mbIgnoreCase = pDok->GetDocOptions().IsIgnoreCase();
     sc::RangeMatrix aMat[2];
     ScAddress aAdr;
     for( short i = 1; i >= 0; i-- )
@@ -983,7 +985,7 @@ sc::RangeMatrix ScInterpreter::CompareMat( sc::CompareOptions* pOptions )
         }
         else if (aMat[0].mpMat || aMat[1].mpMat)
         {
-            short i = ( aMat[0].mpMat ? 0 : 1);
+            size_t i = ( aMat[0].mpMat ? 0 : 1);
             SCSIZE nC, nR;
             aMat[i].mpMat->GetDimensions(nC, nR);
             aRes.mpMat = GetNewMat(nC, nR, false);
@@ -999,46 +1001,7 @@ sc::RangeMatrix ScInterpreter::CompareMat( sc::CompareOptions* pOptions )
 
             ScMatrix& rMat = *aMat[i].mpMat;
             ScMatrix& rResMat = *aRes.mpMat;
-            ScMatrix::PosRef pMatPos(rMat.GetPosition(0, 0));
-            ScMatrixValue aVal;
-            std::vector<double> aResMatValues;
-            aResMatValues.reserve(nC*nR);
-            for (size_t j = 0, n = nC*nR; j < n; ++j)
-            {
-                aVal = rMat.Get(*pMatPos);
-                switch (aVal.nType)
-                {
-                    case SC_MATVAL_VALUE:
-                    case SC_MATVAL_BOOLEAN:
-                    {
-                        aComp.bVal[i] = true;
-                        aComp.nVal[i] = aVal.fVal;
-                        aComp.bEmpty[i] = false;
-                    }
-                    break;
-                    case SC_MATVAL_STRING:
-                    {
-                        aComp.bVal[i] = false;
-                        *aComp.pVal[i] = aVal.aStr.getString();
-                        aComp.bEmpty[i] = false;
-                    }
-                    break;
-                    case SC_MATVAL_EMPTY:
-                    case SC_MATVAL_EMPTYPATH:
-                    {
-                        aComp.bVal[i] = false;
-                        *aComp.pVal[i] = svl::SharedString::getEmptyString().getString();
-                        aComp.bEmpty[i] = aVal.nType == SC_MATVAL_EMPTY;
-                    }
-                    break;
-                    default:
-                        ;
-                }
-
-                aResMatValues.push_back(sc::CompareFunc(pDok->GetDocOptions().IsIgnoreCase(), aComp, pOptions));
-                rMat.NextPosition(*pMatPos);
-            }
-            rResMat.PutDouble(&aResMatValues[0], aResMatValues.size(), 0, 0);
+            rMat.CompareMatrix(rResMat, aComp, i, pOptions);
         }
     }
     nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 164da28..8b45f00 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -23,6 +23,7 @@
 #include "formula/errorcodes.hxx"
 #include "interpre.hxx"
 #include "mtvelements.hxx"
+#include "compare.hxx"
 
 #include <svl/zforlist.hxx>
 #include "svl/sharedstring.hxx"
@@ -264,6 +265,9 @@ public:
 
     double GetMaxValue( bool bTextAsZero ) const;
     double GetMinValue( bool bTextAsZero ) const;
+
+    void CompareMatrix( ScMatrix& rResMat, sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) const;
+
     void GetDoubleArray( std::vector<double>& rArray ) const;
     void MergeDoubleArray( std::vector<double>& rArray, ScMatrix::Op eOp ) const;
 
@@ -1318,6 +1322,97 @@ public:
     }
 };
 
+class CompareMatrixFunc : std::unary_function<MatrixImplType::element_block_type, void>
+{
+    sc::Compare& mrComp;
+    size_t mnMatPos;
+    sc::CompareOptions* mpOptions;
+
+    std::vector<double> maResValues;
+
+    void compare()
+    {
+        maResValues.push_back(sc::CompareFunc(mrComp.mbIgnoreCase, mrComp, mpOptions));
+    }
+
+public:
+    CompareMatrixFunc( size_t nResSize, sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) :
+        mrComp(rComp), mnMatPos(nMatPos), mpOptions(pOptions)
+    {
+        maResValues.reserve(nResSize);
+    }
+
+    void operator() (const MatrixImplType::element_block_node_type& node)
+    {
+        using namespace mdds::mtv;
+
+        switch (node.type)
+        {
+            case mdds::mtm::element_numeric:
+            {
+                typedef MatrixImplType::numeric_block_type block_type;
+
+                block_type::const_iterator it = block_type::begin(*node.data);
+                block_type::const_iterator itEnd = block_type::end(*node.data);
+                for (; it != itEnd; ++it)
+                {
+                    mrComp.bVal[mnMatPos] = true;
+                    mrComp.nVal[mnMatPos] = *it;
+                    mrComp.bEmpty[mnMatPos] = false;
+                    compare();
+                }
+            }
+            break;
+            case mdds::mtm::element_boolean:
+            {
+                typedef MatrixImplType::boolean_block_type block_type;
+
+                block_type::const_iterator it = block_type::begin(*node.data);
+                block_type::const_iterator itEnd = block_type::end(*node.data);
+                for (; it != itEnd; ++it)
+                {
+                    mrComp.bVal[mnMatPos] = true;
+                    mrComp.nVal[mnMatPos] = *it;
+                    mrComp.bEmpty[mnMatPos] = false;
+                    compare();
+                }
+            }
+            break;
+            case mdds::mtm::element_string:
+            {
+                typedef MatrixImplType::string_block_type block_type;
+
+                block_type::const_iterator it = block_type::begin(*node.data);
+                block_type::const_iterator itEnd = block_type::end(*node.data);
+                for (; it != itEnd; ++it)
+                {
+                    const svl::SharedString& rStr = *it;
+                    mrComp.bVal[mnMatPos] = false;
+                    *mrComp.pVal[mnMatPos] = rStr.getString();
+                    mrComp.bEmpty[mnMatPos] = false;
+                    compare();
+                }
+            }
+            break;
+            case mdds::mtm::element_empty:
+            {
+                mrComp.bVal[mnMatPos] = false;
+                *mrComp.pVal[mnMatPos] = svl::SharedString::getEmptyString().getString();
+                mrComp.bEmpty[mnMatPos] = true;
+                for (size_t i = 0; i < node.size; ++i)
+                    compare();
+            }
+            default:
+                ;
+        }
+    }
+
+    const std::vector<double>& getValues() const
+    {
+        return maResValues;
+    }
+};
+
 class ToDoubleArray : std::unary_function<MatrixImplType::element_block_type, void>
 {
     std::vector<double> maArray;
@@ -1496,6 +1591,20 @@ double ScMatrixImpl::GetMinValue( bool bTextAsZero ) const
     return aFunc.getValue();
 }
 
+void ScMatrixImpl::CompareMatrix(
+    ScMatrix& rResMat, sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) const
+{
+    MatrixImplType::size_pair_type aSize = maMat.size();
+    size_t nSize = aSize.column * aSize.row;
+    CompareMatrixFunc aFunc(nSize, rComp, nMatPos, pOptions);
+    maMat.walk(aFunc);
+
+    // We assume the result matrix has the same dimension as this matrix.
+    const std::vector<double>& rResVal = aFunc.getValues();
+    if (nSize == rResVal.size())
+        rResMat.PutDouble(&rResVal[0], rResVal.size(), 0, 0);
+}
+
 void ScMatrixImpl::GetDoubleArray( std::vector<double>& rArray ) const
 {
     MatrixImplType::size_pair_type aSize = maMat.size();
@@ -2006,6 +2115,11 @@ double ScMatrix::GetMinValue( bool bTextAsZero ) const
     return pImpl->GetMinValue(bTextAsZero);
 }
 
+void ScMatrix::CompareMatrix( ScMatrix& rResMat, sc::Compare& rComp, size_t nMatPos, sc::CompareOptions* pOptions ) const
+{
+    pImpl->CompareMatrix(rResMat, rComp, nMatPos, pOptions);
+}
+
 void ScMatrix::GetDoubleArray( std::vector<double>& rArray ) const
 {
     pImpl->GetDoubleArray(rArray);
commit 46fbb3f87d48dd2ba871a21b81594323b2d6a19c
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Oct 17 19:43:01 2013 -0400

    Fix brace styles.
    
    Change-Id: Ieb169d5ef8700067fbf011bbfc18fca6b40c03b8

diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 4b3bbc3..164da28 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -1986,11 +1986,13 @@ size_t ScMatrix::Count(bool bCountStrings) const
     return pImpl->Count(bCountStrings);
 }
 
-size_t ScMatrix::MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const {
+size_t ScMatrix::MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) const
+{
     return pImpl->MatchDoubleInColumns(fValue, nCol1, nCol2);
 }
 
-size_t ScMatrix::MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const {
+size_t ScMatrix::MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, size_t nCol2) const
+{
     return pImpl->MatchStringInColumns(rStr, nCol1, nCol2);
 }
 
commit 8a6d1a87cf7b3d74ff3636f3e11ecda223a9a8f2
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Oct 17 19:23:01 2013 -0400

    Initial attempt to speed up matrix comparison.
    
    And move the value compare code to somewhere public.  I'll be using it
    from the ScMatrix internal.
    
    This change requires mdds 0.9.1 which is yet to be released.
    
    Change-Id: I942133c85b614b3404006fa38af111ace9361fd4

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index f76032a..3cd88db 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -195,6 +195,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
 	sc/source/core/tool/chartpos \
 	sc/source/core/tool/chgtrack \
 	sc/source/core/tool/chgviset \
+	sc/source/core/tool/compare \
 	sc/source/core/tool/compiler \
 	sc/source/core/tool/consoli  \
 	sc/source/core/tool/dbdata \
diff --git a/sc/inc/compare.hxx b/sc/inc/compare.hxx
new file mode 100644
index 0000000..307b531
--- /dev/null
+++ b/sc/inc/compare.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef SC_COMPARE_HXX
+#define SC_COMPARE_HXX
+
+#include "queryentry.hxx"
+
+#include "rtl/ustring.hxx"
+
+class ScDocument;
+
+namespace sc {
+
+struct Compare
+{
+    double nVal[2];
+    OUString* pVal[2];
+    bool bVal[2];
+    bool bEmpty[2];
+
+    Compare( OUString* p1, OUString* p2 )
+    {
+        pVal[0] = p1;
+        pVal[1] = p2;
+        bEmpty[0] = false;
+        bEmpty[1] = false;
+    }
+};
+
+struct CompareOptions
+{
+    ScQueryEntry        aQueryEntry;
+    bool                bRegEx;
+    bool                bMatchWholeCell;
+    bool                bIgnoreCase;
+
+    CompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg );
+private:
+    // Not implemented, prevent usage.
+    CompareOptions();
+    CompareOptions( const CompareOptions & );
+    CompareOptions& operator=( const CompareOptions & );
+};
+
+double CompareFunc( bool bIgnoreCase, const Compare& rComp, CompareOptions* pOptions = NULL );
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index b997506..edd8cbd 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -25,8 +25,10 @@
 #include "formula/errorcodes.hxx"
 #include "scdllapi.h"
 #include <rtl/ustring.hxx>
+#include "svl/sharedstring.hxx"
 
 #include <boost/intrusive_ptr.hpp>
+#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
 
 #define DEBUG_MATRIX 0
 
@@ -34,8 +36,6 @@ class ScInterpreter;
 class SvNumberFormatter;
 class ScMatrixImpl;
 
-namespace svl { class SharedString; }
-
 /**
  * Try NOT to use this struct.  This struct should go away in a hopefully
  * not so distant futture.
@@ -43,11 +43,11 @@ namespace svl { class SharedString; }
 struct ScMatrixValue
 {
     double fVal;
-    OUString aStr;
+    svl::SharedString aStr;
     ScMatValType nType;
 
     /// Only valid if ScMatrix methods indicate so!
-    const OUString& GetString() const { return aStr; }
+    OUString GetString() const { return aStr.getString(); }
 
     /// Only valid if ScMatrix methods indicate that this is no string!
     sal_uInt16 GetError() const         { return GetDoubleErrorValue( fVal); }
@@ -137,6 +137,31 @@ public:
             mfFirst(r.mfFirst), mfRest(r.mfRest), mnCount(r.mnCount) {}
     };
 
+    struct Pos;
+    struct ConstPos;
+
+    static void DeletePosition( const Pos* p );
+    static void DeletePosition( const ConstPos* p );
+
+    struct PosDeleter : std::unary_function<const Pos*, void>
+    {
+        void operator() (const Pos* p)
+        {
+            DeletePosition(p);
+        }
+    };
+
+    struct ConstPosDeleter : std::unary_function<const ConstPos*, void>
+    {
+        void operator() (const ConstPos* p)
+        {
+            DeletePosition(p);
+        }
+    };
+
+    typedef boost::interprocess::unique_ptr<Pos, PosDeleter> PosRef;
+    typedef boost::interprocess::unique_ptr<ConstPos, PosDeleter> ConstPosRef;
+
     /// The maximum number of elements a matrix may have at runtime.
     inline static size_t GetElementsMax()
     {
@@ -289,6 +314,8 @@ public:
     /// @ATTENTION: If bString the ScMatrixValue->pS may still be NULL to indicate
     /// an empty string!
     ScMatrixValue Get( SCSIZE nC, SCSIZE nR) const;
+    ScMatrixValue Get( const Pos& rPos ) const;
+    ScMatrixValue Get( const ConstPos& rPos ) const;
 
     /// @return <TRUE/> if string or empty or empty path, in fact non-value.
     sal_Bool IsString( SCSIZE nIndex ) const;
@@ -317,6 +344,31 @@ public:
     /// @return <TRUE/> if entire matrix is numeric, including booleans, with no strings or empties
     sal_Bool IsNumeric() const;
 
+    Pos* GetPosition( size_t nC, size_t nR );
+    ConstPos* GetConstPosition( size_t nC, size_t nR ) const;
+
+    bool NextPosition( Pos& rPos );
+    bool NextPosition( ConstPos& rPos ) const;
+
+    bool IsValue( const Pos& rPos ) const;
+    bool IsValue( const ConstPos& rPos ) const;
+
+    bool IsEmpty( const Pos& rPos ) const;
+    bool IsEmpty( const ConstPos& rPos ) const;
+
+    double GetDouble( const Pos& rPos ) const;
+    double GetDouble( const ConstPos& rPos ) const;
+
+    svl::SharedString GetString( const Pos& rPos ) const;
+    svl::SharedString GetString( const ConstPos& rPos ) const;
+
+    void PutDouble( double fVal, Pos& rPos );
+    void PutString( const svl::SharedString& rStr, Pos& rPos );
+    void PutEmpty( Pos& rPos );
+    void PutEmptyPath( Pos& rPos );
+    void PutError( sal_uInt16 nErr, Pos& rPos );
+    void PutBoolean( bool bVal, Pos& rPos );
+
     void MatTrans( ScMatrix& mRes) const;
     void MatCopy ( ScMatrix& mRes) const;
 
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 9bba942..a98b2d2 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -1458,7 +1458,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.aStr == "Test");
+            CPPUNIT_ASSERT_MESSAGE("element value is not what is expected", rVal.aStr.getString() == "Test");
         }
         else if (nCol == 8 && nRow == 11)
         {
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 29c722b..b9c7b08 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -42,8 +42,6 @@ struct ScQueryParam;
 struct ScDBQueryParamBase;
 struct ScQueryEntry;
 
-struct ScCompare;
-struct ScCompareOptions;
 struct ScSingleRefData;
 struct ScComplexRefData;
 
@@ -54,6 +52,8 @@ struct ScRefCellValue;
 namespace sc {
 
 struct RangeMatrix;
+struct Compare;
+struct CompareOptions;
 
 }
 
@@ -382,16 +382,12 @@ void ScChoseJump();
 // Returns true if last jump was executed and result matrix pushed.
 bool JumpMatrix( short nStackLevel );
 
-/** @param pOptions
-        NULL means case sensitivity document option is to be used!
- */
-double CompareFunc( const ScCompare& rComp, ScCompareOptions* pOptions = NULL );
 double Compare();
 /** @param pOptions
         NULL means case sensitivity document option is to be used!
  */
-sc::RangeMatrix CompareMat( ScCompareOptions* pOptions = NULL );
-ScMatrixRef QueryMat( const ScMatrixRef& pMat, ScCompareOptions& rOptions );
+sc::RangeMatrix CompareMat( sc::CompareOptions* pOptions = NULL );
+ScMatrixRef QueryMat( const ScMatrixRef& pMat, sc::CompareOptions& rOptions );
 void ScEqual();
 void ScNotEqual();
 void ScLess();
diff --git a/sc/source/core/tool/compare.cxx b/sc/source/core/tool/compare.cxx
new file mode 100644
index 0000000..ece2ff2
--- /dev/null
+++ b/sc/source/core/tool/compare.cxx
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "compare.hxx"
+
+#include "document.hxx"
+#include "docoptio.hxx"
+
+#include "unotools/textsearch.hxx"
+
+namespace sc {
+
+CompareOptions::CompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg ) :
+    aQueryEntry(rEntry),
+    bRegEx(bReg),
+    bMatchWholeCell(pDoc->GetDocOptions().IsMatchWholeCell()),
+    bIgnoreCase(true)
+{
+    bRegEx = (bRegEx && (aQueryEntry.eOp == SC_EQUAL || aQueryEntry.eOp == SC_NOT_EQUAL));
+    // Interpreter functions usually are case insensitive, except the simple
+    // comparison operators, for which these options aren't used. Override in
+    // struct if needed.
+}
+
+/** @param pOptions
+        NULL means case sensitivity document option is to be used!
+ */
+double CompareFunc( bool bIgnoreCase, const Compare& rComp, CompareOptions* pOptions )
+{
+    // Keep DoubleError if encountered
+    // #i40539# if bEmpty is set, bVal/nVal are uninitialized
+    if ( !rComp.bEmpty[0] && rComp.bVal[0] && !::rtl::math::isFinite( rComp.nVal[0]))
+        return rComp.nVal[0];
+    if ( !rComp.bEmpty[1] && rComp.bVal[1] && !::rtl::math::isFinite( rComp.nVal[1]))
+        return rComp.nVal[1];
+
+    size_t nStringQuery = 0;    // 0:=no, 1:=0, 2:=1
+    double fRes = 0;
+    if ( rComp.bEmpty[ 0 ] )
+    {
+        if ( rComp.bEmpty[ 1 ] )
+            ;       // empty cell == empty cell, fRes 0
+        else if( rComp.bVal[ 1 ] )
+        {
+            if ( !::rtl::math::approxEqual( rComp.nVal[ 1 ], 0.0 ) )
+            {
+                if ( rComp.nVal[ 1 ] < 0.0 )
+                    fRes = 1;       // empty cell > -x
+                else
+                    fRes = -1;      // empty cell < x
+            }
+            // else: empty cell == 0.0
+        }
+        else
+        {
+            if ( !rComp.pVal[ 1 ]->isEmpty() )
+                fRes = -1;      // empty cell < "..."
+            // else: empty cell == ""
+        }
+    }
+    else if ( rComp.bEmpty[ 1 ] )
+    {
+        if( rComp.bVal[ 0 ] )
+        {
+            if ( !::rtl::math::approxEqual( rComp.nVal[ 0 ], 0.0 ) )
+            {
+                if ( rComp.nVal[ 0 ] < 0.0 )
+                    fRes = -1;      // -x < empty cell
+                else
+                    fRes = 1;       // x > empty cell
+            }
+            // else: empty cell == 0.0
+        }
+        else
+        {
+            if ( !rComp.pVal[ 0 ]->isEmpty() )
+                fRes = 1;       // "..." > empty cell
+            // else: "" == empty cell
+        }
+    }
+    else if( rComp.bVal[ 0 ] )
+    {
+        if( rComp.bVal[ 1 ] )
+        {
+            if ( !::rtl::math::approxEqual( rComp.nVal[ 0 ], rComp.nVal[ 1 ] ) )
+            {
+                if( rComp.nVal[ 0 ] - rComp.nVal[ 1 ] < 0 )
+                    fRes = -1;
+                else
+                    fRes = 1;
+            }
+        }
+        else
+        {
+            fRes = -1;          // number is less than string
+            nStringQuery = 2;   // 1+1
+        }
+    }
+    else if( rComp.bVal[ 1 ] )
+    {
+        fRes = 1;               // string is greater than number
+        nStringQuery = 1;       // 0+1
+    }
+    else
+    {
+        // Both strings.
+        if (pOptions)
+        {
+            // All similar to ScTable::ValidQuery(), *rComp.pVal[1] actually
+            // is/must be identical to *rEntry.pStr, which is essential for
+            // regex to work through GetSearchTextPtr().
+            ScQueryEntry& rEntry = pOptions->aQueryEntry;
+            OSL_ENSURE(rEntry.GetQueryItem().maString.getString().equals(*rComp.pVal[1]), "ScInterpreter::CompareFunc: broken options");
+            if (pOptions->bRegEx)
+            {
+                sal_Int32 nStart = 0;
+                sal_Int32 nStop  = rComp.pVal[0]->getLength();
+                bool bMatch = rEntry.GetSearchTextPtr(
+                        !pOptions->bIgnoreCase)->SearchForward( *rComp.pVal[0],
+                            &nStart, &nStop);
+                if (bMatch && pOptions->bMatchWholeCell && (nStart != 0 || nStop != rComp.pVal[0]->getLength()))
+                    bMatch = false;     // RegEx must match entire string.
+                fRes = (bMatch ? 0 : 1);
+            }
+            else if (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)
+            {
+                ::utl::TransliterationWrapper* pTransliteration =
+                    (pOptions->bIgnoreCase ? ScGlobal::GetpTransliteration() :
+                     ScGlobal::GetCaseTransliteration());
+                bool bMatch;
+                if (pOptions->bMatchWholeCell)
+                    bMatch = pTransliteration->isEqual( *rComp.pVal[0], *rComp.pVal[1]);
+                else
+                {
+                    OUString aCell( pTransliteration->transliterate(
+                                *rComp.pVal[0], ScGlobal::eLnge, 0,
+                                rComp.pVal[0]->getLength(), NULL));
+                    OUString aQuer( pTransliteration->transliterate(
+                                *rComp.pVal[1], ScGlobal::eLnge, 0,
+                                rComp.pVal[1]->getLength(), NULL));
+                    bMatch = (aCell.indexOf( aQuer ) != -1);
+                }
+                fRes = (bMatch ? 0 : 1);
+            }
+            else if (pOptions->bIgnoreCase)
+                fRes = (double) ScGlobal::GetCollator()->compareString(
+                        *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
+            else
+                fRes = (double) ScGlobal::GetCaseCollator()->compareString(
+                        *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
+        }
+        else if (bIgnoreCase)
+            fRes = (double) ScGlobal::GetCollator()->compareString(
+                *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
+        else
+            fRes = (double) ScGlobal::GetCaseCollator()->compareString(
+                *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
+    }
+
+    if (nStringQuery && pOptions)
+    {
+        const ScQueryEntry& rEntry = pOptions->aQueryEntry;
+        const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
+        if (!rItems.empty())
+        {
+            const ScQueryEntry::Item& rItem = rItems[0];
+            if (rItem.meType != ScQueryEntry::ByString && !rItem.maString.isEmpty() &&
+                (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL))
+            {
+                // As in ScTable::ValidQuery() match a numeric string for a
+                // number query that originated from a string, e.g. in SUMIF
+                // and COUNTIF. Transliteration is not needed here.
+                bool bEqual = (*rComp.pVal[nStringQuery-1]) == rItem.maString.getString();
+                // match => fRes=0, else fRes=1
+                fRes = (rEntry.eOp == SC_NOT_EQUAL) ? bEqual : !bEqual;
+            }
+        }
+    }
+
+    return fRes;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index d1e53df..c60b871 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -57,6 +57,7 @@
 #include "queryparam.hxx"
 #include "queryentry.hxx"
 #include "tokenarray.hxx"
+#include "compare.hxx"
 
 #include <comphelper/processfactory.hxx>
 #include <comphelper/string.hxx>
@@ -81,41 +82,6 @@ bool ScInterpreter::bGlobalStackInUse = false;
 using namespace formula;
 using ::std::auto_ptr;
 
-struct ScCompare
-{
-    double  nVal[2];
-    OUString* pVal[2];
-    bool    bVal[2];
-    bool    bEmpty[2];
-        ScCompare( OUString* p1, OUString* p2 )
-        {
-            pVal[ 0 ] = p1;
-            pVal[ 1 ] = p2;
-            bEmpty[0] = false;
-            bEmpty[1] = false;
-        }
-};
-
-struct ScCompareOptions
-{
-    ScQueryEntry        aQueryEntry;
-    bool                bRegEx;
-    bool                bMatchWholeCell;
-    bool                bIgnoreCase;
-
-                        ScCompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg );
-private:
-                        // Not implemented, prevent usage.
-                        ScCompareOptions();
-                        ScCompareOptions( const ScCompareOptions & );
-     ScCompareOptions&  operator=( const ScCompareOptions & );
-};
-
-//-----------------------------------------------------------------------------
-// Functions
-//-----------------------------------------------------------------------------
-
-
 void ScInterpreter::ScIfJump()
 {
     const short* pJump = pCur->GetJump();
@@ -823,180 +789,10 @@ bool ScInterpreter::JumpMatrix( short nStackLevel )
     return false;
 }
 
-
-ScCompareOptions::ScCompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg ) :
-    aQueryEntry(rEntry),
-    bRegEx(bReg),
-    bMatchWholeCell(pDoc->GetDocOptions().IsMatchWholeCell()),
-    bIgnoreCase(true)
-{
-    bRegEx = (bRegEx && (aQueryEntry.eOp == SC_EQUAL || aQueryEntry.eOp == SC_NOT_EQUAL));
-    // Interpreter functions usually are case insensitive, except the simple
-    // comparison operators, for which these options aren't used. Override in
-    // struct if needed.
-}
-
-
-double ScInterpreter::CompareFunc( const ScCompare& rComp, ScCompareOptions* pOptions )
-{
-    // Keep DoubleError if encountered
-    // #i40539# if bEmpty is set, bVal/nVal are uninitialized
-    if ( !rComp.bEmpty[0] && rComp.bVal[0] && !::rtl::math::isFinite( rComp.nVal[0]))
-        return rComp.nVal[0];
-    if ( !rComp.bEmpty[1] && rComp.bVal[1] && !::rtl::math::isFinite( rComp.nVal[1]))
-        return rComp.nVal[1];
-
-    size_t nStringQuery = 0;    // 0:=no, 1:=0, 2:=1
-    double fRes = 0;
-    if ( rComp.bEmpty[ 0 ] )
-    {
-        if ( rComp.bEmpty[ 1 ] )
-            ;       // empty cell == empty cell, fRes 0
-        else if( rComp.bVal[ 1 ] )
-        {
-            if ( !::rtl::math::approxEqual( rComp.nVal[ 1 ], 0.0 ) )
-            {
-                if ( rComp.nVal[ 1 ] < 0.0 )
-                    fRes = 1;       // empty cell > -x
-                else
-                    fRes = -1;      // empty cell < x
-            }
-            // else: empty cell == 0.0
-        }
-        else
-        {
-            if ( !rComp.pVal[ 1 ]->isEmpty() )
-                fRes = -1;      // empty cell < "..."
-            // else: empty cell == ""
-        }
-    }
-    else if ( rComp.bEmpty[ 1 ] )
-    {
-        if( rComp.bVal[ 0 ] )
-        {
-            if ( !::rtl::math::approxEqual( rComp.nVal[ 0 ], 0.0 ) )
-            {
-                if ( rComp.nVal[ 0 ] < 0.0 )
-                    fRes = -1;      // -x < empty cell
-                else
-                    fRes = 1;       // x > empty cell
-            }
-            // else: empty cell == 0.0
-        }
-        else
-        {
-            if ( !rComp.pVal[ 0 ]->isEmpty() )
-                fRes = 1;       // "..." > empty cell
-            // else: "" == empty cell
-        }
-    }
-    else if( rComp.bVal[ 0 ] )
-    {
-        if( rComp.bVal[ 1 ] )
-        {
-            if ( !::rtl::math::approxEqual( rComp.nVal[ 0 ], rComp.nVal[ 1 ] ) )
-            {
-                if( rComp.nVal[ 0 ] - rComp.nVal[ 1 ] < 0 )
-                    fRes = -1;
-                else
-                    fRes = 1;
-            }
-        }
-        else
-        {
-            fRes = -1;          // number is less than string
-            nStringQuery = 2;   // 1+1
-        }
-    }
-    else if( rComp.bVal[ 1 ] )
-    {
-        fRes = 1;               // string is greater than number
-        nStringQuery = 1;       // 0+1
-    }
-    else
-    {
-        // Both strings.
-        if (pOptions)
-        {
-            // All similar to ScTable::ValidQuery(), *rComp.pVal[1] actually
-            // is/must be identical to *rEntry.pStr, which is essential for
-            // regex to work through GetSearchTextPtr().
-            ScQueryEntry& rEntry = pOptions->aQueryEntry;
-            OSL_ENSURE(rEntry.GetQueryItem().maString.getString().equals(*rComp.pVal[1]), "ScInterpreter::CompareFunc: broken options");
-            if (pOptions->bRegEx)
-            {
-                sal_Int32 nStart = 0;
-                sal_Int32 nStop  = rComp.pVal[0]->getLength();
-                bool bMatch = rEntry.GetSearchTextPtr(
-                        !pOptions->bIgnoreCase)->SearchForward( *rComp.pVal[0],
-                            &nStart, &nStop);
-                if (bMatch && pOptions->bMatchWholeCell && (nStart != 0 || nStop != rComp.pVal[0]->getLength()))
-                    bMatch = false;     // RegEx must match entire string.
-                fRes = (bMatch ? 0 : 1);
-            }
-            else if (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)
-            {
-                ::utl::TransliterationWrapper* pTransliteration =
-                    (pOptions->bIgnoreCase ? ScGlobal::GetpTransliteration() :
-                     ScGlobal::GetCaseTransliteration());
-                bool bMatch;
-                if (pOptions->bMatchWholeCell)
-                    bMatch = pTransliteration->isEqual( *rComp.pVal[0], *rComp.pVal[1]);
-                else
-                {
-                    OUString aCell( pTransliteration->transliterate(
-                                *rComp.pVal[0], ScGlobal::eLnge, 0,
-                                rComp.pVal[0]->getLength(), NULL));
-                    OUString aQuer( pTransliteration->transliterate(
-                                *rComp.pVal[1], ScGlobal::eLnge, 0,
-                                rComp.pVal[1]->getLength(), NULL));
-                    bMatch = (aCell.indexOf( aQuer ) != -1);
-                }
-                fRes = (bMatch ? 0 : 1);
-            }
-            else if (pOptions->bIgnoreCase)
-                fRes = (double) ScGlobal::GetCollator()->compareString(
-                        *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
-            else
-                fRes = (double) ScGlobal::GetCaseCollator()->compareString(
-                        *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
-        }
-        else if (pDok->GetDocOptions().IsIgnoreCase())
-            fRes = (double) ScGlobal::GetCollator()->compareString(
-                *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
-        else
-            fRes = (double) ScGlobal::GetCaseCollator()->compareString(
-                *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
-    }
-
-    if (nStringQuery && pOptions)
-    {
-        const ScQueryEntry& rEntry = pOptions->aQueryEntry;
-        const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
-        if (!rItems.empty())
-        {
-            const ScQueryEntry::Item& rItem = rItems[0];
-            if (rItem.meType != ScQueryEntry::ByString && !rItem.maString.isEmpty() &&
-                (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL))
-            {
-                // As in ScTable::ValidQuery() match a numeric string for a
-                // number query that originated from a string, e.g. in SUMIF
-                // and COUNTIF. Transliteration is not needed here.
-                bool bEqual = (*rComp.pVal[nStringQuery-1]) == rItem.maString.getString();
-                // match => fRes=0, else fRes=1
-                fRes = (rEntry.eOp == SC_NOT_EQUAL) ? bEqual : !bEqual;
-            }
-        }
-    }
-
-    return fRes;
-}
-
-
 double ScInterpreter::Compare()
 {
     OUString aVal1, aVal2;
-    ScCompare aComp( &aVal1, &aVal2 );
+    sc::Compare aComp( &aVal1, &aVal2 );
     for( short i = 1; i >= 0; i-- )
     {
         switch ( GetRawStackType() )
@@ -1078,14 +874,14 @@ double ScInterpreter::Compare()
     if( nGlobalError )
         return 0;
     nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
-    return CompareFunc( aComp );
+    return sc::CompareFunc(pDok->GetDocOptions().IsIgnoreCase(), aComp);
 }
 
 
-sc::RangeMatrix ScInterpreter::CompareMat( ScCompareOptions* pOptions )
+sc::RangeMatrix ScInterpreter::CompareMat( sc::CompareOptions* pOptions )
 {
     OUString aVal1, aVal2;
-    ScCompare aComp( &aVal1, &aVal2 );
+    sc::Compare aComp( &aVal1, &aVal2 );
     sc::RangeMatrix aMat[2];
     ScAddress aAdr;
     for( short i = 1; i >= 0; i-- )
@@ -1178,7 +974,7 @@ sc::RangeMatrix ScInterpreter::CompareMat( ScCompareOptions* pOptions )
                                 aComp.bEmpty[i] = false;
                             }
                         }
-                        aRes.mpMat->PutDouble(CompareFunc(aComp, pOptions), j, k);
+                        aRes.mpMat->PutDouble(sc::CompareFunc(pDok->GetDocOptions().IsIgnoreCase(), aComp, pOptions), j, k);
                     }
                     else
                         aRes.mpMat->PutString(mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE)), j, k);
@@ -1190,7 +986,7 @@ sc::RangeMatrix ScInterpreter::CompareMat( ScCompareOptions* pOptions )
             short i = ( aMat[0].mpMat ? 0 : 1);
             SCSIZE nC, nR;
             aMat[i].mpMat->GetDimensions(nC, nR);
-            aRes.mpMat = GetNewMat( nC, nR);
+            aRes.mpMat = GetNewMat(nC, nR, false);
             if (!aRes.mpMat)
                 return aRes;
 
@@ -1201,25 +997,48 @@ sc::RangeMatrix ScInterpreter::CompareMat( ScCompareOptions* pOptions )
             aRes.mnRow2 = aMat[i].mnRow2;
             aRes.mnTab2 = aMat[i].mnTab2;
 
-            for (SCSIZE j = 0; j < nC; ++j)
+            ScMatrix& rMat = *aMat[i].mpMat;
+            ScMatrix& rResMat = *aRes.mpMat;
+            ScMatrix::PosRef pMatPos(rMat.GetPosition(0, 0));
+            ScMatrixValue aVal;
+            std::vector<double> aResMatValues;
+            aResMatValues.reserve(nC*nR);
+            for (size_t j = 0, n = nC*nR; j < n; ++j)
             {
-                for (SCSIZE k = 0; k < nR; ++k)
+                aVal = rMat.Get(*pMatPos);
+                switch (aVal.nType)
                 {
-                    if (aMat[i].mpMat->IsValue(j, k))
+                    case SC_MATVAL_VALUE:
+                    case SC_MATVAL_BOOLEAN:
                     {
                         aComp.bVal[i] = true;
-                        aComp.nVal[i] = aMat[i].mpMat->GetDouble(j, k);
+                        aComp.nVal[i] = aVal.fVal;
                         aComp.bEmpty[i] = false;
                     }
-                    else
+                    break;
+                    case SC_MATVAL_STRING:
                     {
                         aComp.bVal[i] = false;
-                        *aComp.pVal[i] = aMat[i].mpMat->GetString(j, k).getString();
-                        aComp.bEmpty[i] = aMat[i].mpMat->IsEmpty(j, k);
+                        *aComp.pVal[i] = aVal.aStr.getString();
+                        aComp.bEmpty[i] = false;
                     }
-                    aRes.mpMat->PutDouble(CompareFunc(aComp, pOptions), j, k);
+                    break;
+                    case SC_MATVAL_EMPTY:
+                    case SC_MATVAL_EMPTYPATH:
+                    {
+                        aComp.bVal[i] = false;
+                        *aComp.pVal[i] = svl::SharedString::getEmptyString().getString();
+                        aComp.bEmpty[i] = aVal.nType == SC_MATVAL_EMPTY;
+                    }
+                    break;
+                    default:
+                        ;
                 }
+
+                aResMatValues.push_back(sc::CompareFunc(pDok->GetDocOptions().IsIgnoreCase(), aComp, pOptions));
+                rMat.NextPosition(*pMatPos);
             }
+            rResMat.PutDouble(&aResMatValues[0], aResMatValues.size(), 0, 0);
         }
     }
     nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
@@ -1227,7 +1046,7 @@ sc::RangeMatrix ScInterpreter::CompareMat( ScCompareOptions* pOptions )
 }
 
 
-ScMatrixRef ScInterpreter::QueryMat( const ScMatrixRef& pMat, ScCompareOptions& rOptions )
+ScMatrixRef ScInterpreter::QueryMat( const ScMatrixRef& pMat, sc::CompareOptions& rOptions )
 {
     short nSaveCurFmtType = nCurFmtType;
     short nSaveFuncFmtType = nFuncFmtType;
@@ -5132,7 +4951,7 @@ double ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc )
             if (pQueryMatrix)
             {
                 // Never case-sensitive.
-                ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
+                sc::CompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
                 ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
                 if (nGlobalError || !pResultMatrix)
                 {
@@ -5427,7 +5246,7 @@ void ScInterpreter::ScCountIf()
                 if (pQueryMatrix)
                 {
                     // Never case-sensitive.
-                    ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
+                    sc::CompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
                     ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
                     if (nGlobalError || !pResultMatrix)
                     {
@@ -5683,7 +5502,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                 if (pQueryMatrix)
                 {
                     // Never case-sensitive.
-                    ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
+                    sc::CompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
                     ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
                     if (nGlobalError || !pResultMatrix)
                     {
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index af824ac..4b3bbc3 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -64,10 +64,28 @@ struct custom_string_trait
     typedef mdds::mtv::custom_block_func1<sc::string_block> element_block_func;
 };
 
-namespace {
-
 typedef mdds::multi_type_matrix<custom_string_trait> MatrixImplType;
 
+struct ScMatrix::Pos
+{
+    MatrixImplType::position_type maPos;
+    MatrixImplType::position_type maPosFlag;
+};
+
+struct ScMatrix::ConstPos
+{
+    MatrixImplType::const_position_type maPos;
+    MatrixImplType::const_position_type maPosFlag;
+
+    ConstPos() {}
+    ConstPos( const ScMatrix::ConstPos& r ) :
+        maPos(r.maPos), maPosFlag(r.maPosFlag) {}
+    ConstPos( const ScMatrix::Pos& r ) :
+        maPos(r.maPos), maPosFlag(r.maPosFlag) {}
+};
+
+namespace {
+
 struct ElemEqualZero : public unary_function<double, bool>
 {
     bool operator() (double val) const
@@ -195,6 +213,7 @@ public:
     svl::SharedString GetString( SCSIZE nIndex) const;
     svl::SharedString GetString( SvNumberFormatter& rFormatter, SCSIZE nC, SCSIZE nR) const;
     ScMatrixValue Get(SCSIZE nC, SCSIZE nR) const;
+    ScMatrixValue Get( const ScMatrix::ConstPos& rPos ) const;
     bool IsString( SCSIZE nIndex ) const;
     bool IsString( SCSIZE nC, SCSIZE nR ) const;
     bool IsEmpty( SCSIZE nC, SCSIZE nR ) const;
@@ -204,6 +223,25 @@ public:
     bool IsValueOrEmpty( SCSIZE nC, SCSIZE nR ) const;
     bool IsBoolean( SCSIZE nC, SCSIZE nR ) const;
     bool IsNumeric() const;
+
+    ScMatrix::Pos* GetPosition( size_t nC, size_t nR );
+    ScMatrix::ConstPos* GetConstPosition( size_t nC, size_t nR ) const;
+
+    bool NextPosition( ScMatrix::Pos& rPos );
+    bool NextPosition( ScMatrix::ConstPos& rPos ) const;
+
+    bool IsValue( const ScMatrix::ConstPos& rPos ) const;
+    bool IsEmpty( const ScMatrix::ConstPos& rPos ) const;
+    double GetDouble( const ScMatrix::ConstPos& rPos ) const;
+    svl::SharedString GetString( const ScMatrix::ConstPos& rPos ) const;
+
+    void PutDouble( double fVal, ScMatrix::Pos& rPos );
+    void PutString( const svl::SharedString& rStr, ScMatrix::Pos& rPos );
+    void PutEmpty( ScMatrix::Pos& rPos );
+    void PutEmptyPath( ScMatrix::Pos& rPos );
+    void PutError( sal_uInt16 nErr, ScMatrix::Pos& rPos );
+    void PutBoolean( bool bVal, ScMatrix::Pos& rPos );
+
     void MatCopy(ScMatrixImpl& mRes) const;
     void MatTrans(ScMatrixImpl& mRes) const;
     void FillDouble( double fVal, SCSIZE nC1, SCSIZE nR1, SCSIZE nC2, SCSIZE nR2 );
@@ -482,7 +520,7 @@ svl::SharedString ScMatrixImpl::GetString(SCSIZE nC, SCSIZE nR) const
             case mdds::mtm::element_string:
                 return maMat.get_string(aPos);
             case mdds::mtm::element_empty:
-                return svl::SharedString(EMPTY_OUSTRING);
+                return svl::SharedString::getEmptyString();
             case mdds::mtm::element_numeric:
             case mdds::mtm::element_boolean:
                 OSL_FAIL("ScMatrixImpl::GetString: access error, no string");
@@ -496,7 +534,7 @@ svl::SharedString ScMatrixImpl::GetString(SCSIZE nC, SCSIZE nR) const
     {
         OSL_FAIL("ScMatrixImpl::GetString: dimension error");
     }
-    return svl::SharedString(EMPTY_OUSTRING);
+    return svl::SharedString::getEmptyString();
 }
 
 svl::SharedString ScMatrixImpl::GetString( SCSIZE nIndex) const
@@ -575,7 +613,7 @@ ScMatrixValue ScMatrixImpl::Get(SCSIZE nC, SCSIZE nR) const
             break;
             case mdds::mtm::element_string:
                 aVal.nType = SC_MATVAL_STRING;
-                aVal.aStr = maMat.get_string(aPos).getString();
+                aVal.aStr = maMat.get_string(aPos);
             break;
             case mdds::mtm::element_empty:
                 // Empty path equals empty plus flag.
@@ -592,6 +630,34 @@ ScMatrixValue ScMatrixImpl::Get(SCSIZE nC, SCSIZE nR) const
     return aVal;
 }
 
+ScMatrixValue ScMatrixImpl::Get( const ScMatrix::ConstPos& rPos ) const
+{
+    ScMatrixValue aVal;
+    mdds::mtm::element_t eType = maMat.get_type(rPos.maPos);
+    switch (eType)
+    {
+        case mdds::mtm::element_boolean:
+            aVal.nType = SC_MATVAL_BOOLEAN;
+            aVal.fVal = maMat.get_boolean(rPos.maPos);
+        break;
+        case mdds::mtm::element_numeric:
+            aVal.nType = SC_MATVAL_VALUE;
+            aVal.fVal = MatrixImplType::numeric_block_type::at(*rPos.maPos.first->data, rPos.maPos.second);
+        break;
+        case mdds::mtm::element_string:
+            aVal.nType = SC_MATVAL_STRING;
+            aVal.aStr = MatrixImplType::string_block_type::at(*rPos.maPos.first->data, rPos.maPos.second);
+        break;
+        case mdds::mtm::element_empty:
+            // Empty path equals empty plus flag.
+            aVal.nType = maMatFlag.get_boolean(rPos.maPosFlag) ? SC_MATVAL_EMPTYPATH : SC_MATVAL_EMPTY;
+            aVal.fVal = 0.0;
+        default:
+            ;
+    }
+    return aVal;
+}
+
 bool ScMatrixImpl::IsString( SCSIZE nIndex ) const
 {
     SCSIZE nC, nR;
@@ -677,6 +743,123 @@ bool ScMatrixImpl::IsNumeric() const
     return maMat.numeric();
 }
 
+ScMatrix::Pos* ScMatrixImpl::GetPosition( size_t nC, size_t nR )
+{
+    ScMatrix::Pos* pRet = new ScMatrix::Pos;
+    pRet->maPos = maMat.position(nR, nC);
+    pRet->maPosFlag = maMatFlag.position(nR, nC);
+    return pRet;
+}
+
+ScMatrix::ConstPos* ScMatrixImpl::GetConstPosition( size_t nC, size_t nR ) const
+{
+    ScMatrix::ConstPos* pRet = new ScMatrix::ConstPos;
+    pRet->maPos = maMat.position(nR, nC);
+    pRet->maPosFlag = maMatFlag.position(nR, nC);
+    return pRet;
+}
+
+bool ScMatrixImpl::NextPosition( ScMatrix::Pos& rPos )
+{
+    rPos.maPos = MatrixImplType::next_position(rPos.maPos);
+    rPos.maPosFlag = MatrixImplType::next_position(rPos.maPosFlag);
+    return rPos.maPos != maMat.end_position();
+}
+
+bool ScMatrixImpl::NextPosition( ScMatrix::ConstPos& rPos ) const
+{
+    rPos.maPos = MatrixImplType::next_position(rPos.maPos);
+    rPos.maPosFlag = MatrixImplType::next_position(rPos.maPosFlag);
+    return rPos.maPos != maMat.end_position();
+}
+
+bool ScMatrixImpl::IsValue( const ScMatrix::ConstPos& rPos ) const
+{
+    switch (maMat.get_type(rPos.maPos))
+    {
+        case mdds::mtm::element_boolean:
+        case mdds::mtm::element_numeric:
+            return true;
+        default:
+            ;
+    }
+    return false;
+}
+
+bool ScMatrixImpl::IsEmpty( const ScMatrix::ConstPos& rPos ) const
+{
+    return maMat.get_type(rPos.maPos) == mdds::mtm::element_empty && !maMatFlag.get_boolean(rPos.maPosFlag);
+}
+
+double ScMatrixImpl::GetDouble( const ScMatrix::ConstPos& rPos ) const
+{
+    double fVal = maMat.get_numeric(rPos.maPos);
+    if (pErrorInterpreter)
+    {
+        sal_uInt16 nError = GetDoubleErrorValue(fVal);
+        if (nError)
+            SetErrorAtInterpreter( nError);
+    }
+    return fVal;
+}
+
+
+svl::SharedString ScMatrixImpl::GetString( const ScMatrix::ConstPos& rPos ) const
+{
+    double fErr = 0.0;
+    switch (maMat.get_type(rPos.maPos))
+    {
+        case mdds::mtm::element_string:
+            return maMat.get_string(rPos.maPos);
+        case mdds::mtm::element_empty:
+            return svl::SharedString::getEmptyString();
+        case mdds::mtm::element_numeric:
+        case mdds::mtm::element_boolean:
+            OSL_FAIL("ScMatrixImpl::GetString: access error, no string");
+            fErr = maMat.get_numeric(rPos.maPos);
+        default:
+            OSL_FAIL("ScMatrixImpl::GetString: access error, no string");
+    }
+
+    SetErrorAtInterpreter(GetDoubleErrorValue(fErr));
+    return svl::SharedString::getEmptyString();
+}
+
+void ScMatrixImpl::PutDouble( double fVal, ScMatrix::Pos& rPos )
+{
+    if (maMat.get_type(rPos.maPos) == mdds::mtm::element_numeric)
+        MatrixImplType::numeric_block_type::at(*rPos.maPos.first->data, rPos.maPos.second) = fVal;
+    else
+        rPos.maPos = maMat.set(rPos.maPos, fVal);
+}
+
+void ScMatrixImpl::PutString( const svl::SharedString& rStr, ScMatrix::Pos& rPos )
+{
+    rPos.maPos = maMat.set(rPos.maPos, rStr);
+}
+
+void ScMatrixImpl::PutEmpty( ScMatrix::Pos& rPos )
+{
+    rPos.maPos = maMat.set_empty(rPos.maPos);
+    rPos.maPosFlag = maMatFlag.set(rPos.maPosFlag, false); // zero flag to indicate that this is 'empty', not 'empty path'.
+}
+
+void ScMatrixImpl::PutEmptyPath( ScMatrix::Pos& rPos )
+{
+    rPos.maPos = maMat.set_empty(rPos.maPos);
+    rPos.maPosFlag = maMatFlag.set(rPos.maPosFlag, true); // non-zero flag to indicate empty 'path'.
+}
+
+void ScMatrixImpl::PutError( sal_uInt16 nErr, ScMatrix::Pos& rPos )
+{
+    rPos.maPos = maMat.set(rPos.maPos, CreateDoubleError(nErr));
+}
+
+void ScMatrixImpl::PutBoolean( bool bVal, ScMatrix::Pos& rPos )
+{
+    rPos.maPos = maMat.set(rPos.maPos, bVal);
+}
+
 void ScMatrixImpl::MatCopy(ScMatrixImpl& mRes) const
 {
     if (maMat.size().row > mRes.maMat.size().row || maMat.size().column > mRes.maMat.size().column)
@@ -1568,6 +1751,16 @@ ScMatrixValue ScMatrix::Get(SCSIZE nC, SCSIZE nR) const
     return pImpl->Get(nC, nR);
 }
 
+ScMatrixValue ScMatrix::Get( const Pos& rPos ) const
+{
+    return pImpl->Get(rPos);
+}
+
+ScMatrixValue ScMatrix::Get( const ConstPos& rPos ) const
+{
+    return pImpl->Get(rPos);
+}
+
 sal_Bool ScMatrix::IsString( SCSIZE nIndex ) const
 {
     return pImpl->IsString(nIndex);
@@ -1613,6 +1806,106 @@ sal_Bool ScMatrix::IsNumeric() const
     return pImpl->IsNumeric();
 }
 
+ScMatrix::Pos* ScMatrix::GetPosition( size_t nC, size_t nR )
+{
+    return pImpl->GetPosition(nC, nR);
+}
+
+ScMatrix::ConstPos* ScMatrix::GetConstPosition( size_t nC, size_t nR ) const
+{
+    return pImpl->GetConstPosition(nC, nR);
+}
+
+void ScMatrix::DeletePosition( const Pos* p )
+{
+    delete p;
+}
+
+void ScMatrix::DeletePosition( const ConstPos* p )
+{
+    delete p;
+}
+
+bool ScMatrix::NextPosition( Pos& rPos )
+{
+    return pImpl->NextPosition(rPos);
+}
+
+bool ScMatrix::NextPosition( ConstPos& rPos ) const
+{
+    return pImpl->NextPosition(rPos);
+}
+
+bool ScMatrix::IsValue( const Pos& rPos ) const
+{
+    return pImpl->IsValue(rPos);
+}
+
+bool ScMatrix::IsValue( const ConstPos& rPos ) const
+{
+    return pImpl->IsValue(rPos);
+}
+
+bool ScMatrix::IsEmpty( const Pos& rPos ) const
+{
+    return pImpl->IsEmpty(rPos);
+}
+
+bool ScMatrix::IsEmpty( const ConstPos& rPos ) const
+{
+    return pImpl->IsEmpty(rPos);
+}
+
+double ScMatrix::GetDouble( const Pos& rPos ) const
+{
+    return pImpl->GetDouble(rPos);
+}
+
+double ScMatrix::GetDouble( const ConstPos& rPos ) const
+{
+    return pImpl->GetDouble(rPos);
+}
+
+svl::SharedString ScMatrix::GetString( const Pos& rPos ) const
+{
+    return pImpl->GetString(rPos);
+}
+
+svl::SharedString ScMatrix::GetString( const ConstPos& rPos ) const
+{
+    return pImpl->GetString(rPos);
+}
+
+void ScMatrix::PutDouble( double fVal, Pos& rPos )
+{
+    pImpl->PutDouble(fVal, rPos);
+}
+
+void ScMatrix::PutString( const svl::SharedString& rStr, Pos& rPos )
+{
+    pImpl->PutString(rStr, rPos);
+}
+
+void ScMatrix::PutEmpty( Pos& rPos )
+{
+    pImpl->PutEmpty(rPos);
+}
+
+void ScMatrix::PutEmptyPath( Pos& rPos )
+{
+    pImpl->PutEmptyPath(rPos);
+}
+
+void ScMatrix::PutError( sal_uInt16 nErr, Pos& rPos )
+{
+    pImpl->PutError(nErr, rPos);
+}
+
+void ScMatrix::PutBoolean( bool bVal, Pos& rPos )
+{
+    pImpl->PutBoolean(bVal, rPos);
+}
+
 void ScMatrix::MatCopy(ScMatrix& mRes) const
 {
     pImpl->MatCopy(*mRes.pImpl);


More information about the Libreoffice-commits mailing list