[Libreoffice-commits] core.git: Branch 'libreoffice-4-4' - sc/inc sc/source

Markus Mohrhard markus.mohrhard at collabora.co.uk
Wed Jan 7 16:53:44 PST 2015


 sc/inc/scmatrix.hxx              |    2 
 sc/source/core/tool/interpr5.cxx |   21 --
 sc/source/core/tool/scmatrix.cxx |  310 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 317 insertions(+), 16 deletions(-)

New commits:
commit 4f29a7766edd19757a8ab2e38bf7fdff36c704b7
Author: Markus Mohrhard <markus.mohrhard at collabora.co.uk>
Date:   Mon Dec 22 00:14:35 2014 +0100

    improve performance of some matrix operations, related fdo#83187
    
     I0e6816a7f0d2dc051dff6a462724cb4a3c155289
    
    fix error in last commit
    
     Icafbe6e5daab64e7431d80c8956143341eb2ef0b
    
    fix a few problems with my matrix commit
    
     I6e3fdf4bd26c952a59ad130dc6e5c9d1f3ff5f07
    
    coverity#1260446 Uninitialized scalar field
    
    and
    
    coverity#1260447 Uninitialized scalar field
    
     I3aa5a1caf776fddc8b6029e96c24aa86b21de880
    
    iterator::operator*() should return a reference
    
    Change-Id: Id09f555c5ece9e5cb60a2ae7bc2456d4343744f5
    Reviewed-on: https://gerrit.libreoffice.org/13676
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Eike Rathke <erack at redhat.com>

diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index 851caa4..6bcd8857 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -385,6 +385,8 @@ public:
     void GetDoubleArray( std::vector<double>& rArray, bool bEmptyAsZero = true ) const;
     void MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const;
 
+    void SubAddOp(bool bSub, double fVal, svl::SharedString aString, ScMatrix& rMat);
+
     ScMatrix& operator+= ( const ScMatrix& r );
 
 #if DEBUG_MATRIX
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index e334846..0d5f907 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -1188,6 +1188,7 @@ void ScInterpreter::ScAdd()
 {
     CalculateAddSub(false);
 }
+
 void ScInterpreter::CalculateAddSub(bool _bSub)
 {
     ScMatrixRef pMat1 = NULL;
@@ -1275,29 +1276,17 @@ void ScInterpreter::CalculateAddSub(bool _bSub)
         }
         SCSIZE nC, nR;
         pMat->GetDimensions(nC, nR);
-        ScMatrixRef pResMat = GetNewMat(nC, nR);
+        ScMatrixRef pResMat = GetNewMat(nC, nR, true);
         if (pResMat)
         {
-            SCSIZE nCount = nC * nR;
+            svl::SharedString aString = mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE));
             if (bFlag || !_bSub )
             {
-                for ( SCSIZE i = 0; i < nCount; i++ )
-                {
-                    if (pMat->IsValue(i))
-                        pResMat->PutDouble( _bSub ? ::rtl::math::approxSub( fVal, pMat->GetDouble(i)) : ::rtl::math::approxAdd( pMat->GetDouble(i), fVal), i);
-                    else
-                        pResMat->PutString(mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE)), i);
-                }
+                pMat->SubAddOp(_bSub, fVal, aString, *pResMat);
             }
             else
             {
-                for ( SCSIZE i = 0; i < nCount; i++ )
-                {
-                    if (pMat->IsValue(i))
-                        pResMat->PutDouble( ::rtl::math::approxSub( pMat->GetDouble(i), fVal), i);
-                    else
-                        pResMat->PutString(mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE)), i);
-                }
+                pMat->SubAddOp(true, fVal, aString, *pResMat);
             }
             PushMatrix(pResMat);
         }
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 429fd5f..b111ddf 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -295,6 +295,9 @@ public:
     void MergeDoubleArray( std::vector<double>& rArray, ScMatrix::Op eOp ) const;
     void AddValues( const ScMatrixImpl& rMat );
 
+    template<typename T>
+    void ApplyOperation(T aOp, ScMatrixImpl& rMat);
+
 #if DEBUG_MATRIX
     void Dump() const;
 #endif
@@ -1858,6 +1861,215 @@ void ScMatrixImpl::AddValues( const ScMatrixImpl& rMat )
     }
 }
 
+namespace Op {
+
+template<typename T>
+struct return_type
+{
+    typedef T type;
+};
+
+template<>
+struct return_type<bool>
+{
+    typedef double type;
+};
+
+template<>
+struct return_type<char>
+{
+    typedef svl::SharedString type;
+};
+
+}
+
+template<typename T, typename U>
+struct wrapped_iterator
+{
+    typedef ::std::bidirectional_iterator_tag iterator_category;
+    typedef typename T::const_iterator::value_type old_value_type;
+    typedef typename Op::return_type<old_value_type>::type value_type;
+    typedef value_type* pointer;
+    typedef value_type& reference;
+    typedef typename T::const_iterator::difference_type difference_type;
+
+    typename T::const_iterator it;
+    mutable value_type val;
+    U maOp;
+
+private:
+
+    value_type calcVal() const
+    {
+        return maOp(*it);
+    }
+
+public:
+
+    wrapped_iterator(typename T::const_iterator it_, U aOp):
+        it(it_),
+        val(value_type()),
+        maOp(aOp)
+    {
+    }
+
+    wrapped_iterator(const wrapped_iterator& r):
+        it(r.it),
+        val(r.val),
+        maOp(r.maOp)
+    {
+    }
+
+    wrapped_iterator& operator=(const wrapped_iterator& r)
+    {
+        it = r.it;
+        return *this;
+    }
+
+    bool operator==(const wrapped_iterator& r) const
+    {
+        return it == r.it;
+    }
+
+    bool operator!=(const wrapped_iterator& r) const
+    {
+        return !operator==(r);
+    }
+
+    wrapped_iterator& operator++()
+    {
+        ++it;
+
+        return *this;
+    }
+
+    wrapped_iterator& operator--()
+    {
+        --it;
+
+        return *this;
+    }
+
+    value_type& operator*() const
+    {
+        val = calcVal();
+        return val;
+    }
+
+    pointer operator->() const
+    {
+        val = calcVal();
+        return &val;
+    }
+};
+
+template<typename T, typename U>
+struct MatrixIteratorWrapper
+{
+private:
+    typename T::const_iterator m_itBegin;
+    typename T::const_iterator m_itEnd;
+    U maOp;
+public:
+    MatrixIteratorWrapper(typename T::const_iterator itBegin, typename T::const_iterator itEnd, U aOp):
+        m_itBegin(itBegin),
+        m_itEnd(itEnd),
+        maOp(aOp)
+    {
+    }
+
+    wrapped_iterator<T, U> begin()
+    {
+        return wrapped_iterator<T, U>(m_itBegin, maOp);
+    }
+
+    wrapped_iterator<T, U> end()
+    {
+        return wrapped_iterator<T, U>(m_itEnd, maOp);
+    }
+};
+
+template<typename T>
+struct MatrixOpWrapper
+{
+private:
+    MatrixImplType& mrMat;
+    MatrixImplType::position_type pos;
+    T maOp;
+
+public:
+    MatrixOpWrapper(MatrixImplType& rMat, T aOp):
+        mrMat(rMat),
+        pos(rMat.position(0,0)),
+        maOp(aOp)
+    {
+    }
+
+    void operator()(const MatrixImplType::element_block_node_type& node)
+    {
+        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);
+                MatrixIteratorWrapper<block_type, T> aFunc(it, itEnd, maOp);
+                pos = mrMat.set(pos,aFunc.begin(), aFunc.end());
+                ++pos.first;
+            }
+            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);
+
+                MatrixIteratorWrapper<block_type, T> aFunc(it, itEnd, maOp);
+                pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
+                ++pos.first;
+            }
+            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);
+
+                MatrixIteratorWrapper<block_type, T> aFunc(it, itEnd, maOp);
+                pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
+                ++pos.first;
+            }
+            break;
+            case mdds::mtm::element_empty:
+            {
+                if (maOp.useFunctionForEmpty())
+                {
+                    std::vector<char> aVec(node.size);
+                    MatrixIteratorWrapper<std::vector<char>, T> aFunc(aVec.begin(), aVec.end(), maOp);
+                    pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
+                    ++pos.first;
+                }
+                else
+                    pos.second += node.size;
+            }
+            break;
+            default:
+                ;
+        }
+    }
+};
+
+template<typename T>
+void ScMatrixImpl::ApplyOperation(T aOp, ScMatrixImpl& rMat)
+{
+    MatrixOpWrapper<T> aFunc(rMat.maMat, aOp);
+    maMat.walk(aFunc);
+}
+
 #if DEBUG_MATRIX
 void ScMatrixImpl::Dump() const
 {
@@ -2283,6 +2495,104 @@ void ScMatrix::MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const
     pImpl->MergeDoubleArray(rArray, eOp);
 }
 
+namespace {
+
+struct AddOp
+{
+private:
+    double mnVal;
+    svl::SharedString maString;
+
+public:
+
+    AddOp(double nVal, svl::SharedString aString):
+        mnVal(nVal),
+        maString(aString)
+    {
+    }
+
+    double operator()(double nVal) const
+    {
+        return nVal + mnVal;
+    }
+
+    double operator()(bool bVal) const
+    {
+        return mnVal + (double)bVal;
+    }
+
+    svl::SharedString operator()(const svl::SharedString&) const
+    {
+        return maString;
+    }
+
+    svl::SharedString operator()(char) const
+    {
+        return maString;
+    }
+
+    bool useFunctionForEmpty() const
+    {
+        return true;
+    }
+};
+
+struct SubOp
+{
+private:
+    double mnVal;
+    svl::SharedString maString;
+
+public:
+
+    SubOp(double nVal, svl::SharedString aString):
+        mnVal(nVal),
+        maString(aString)
+    {
+    }
+
+    double operator()(double nVal) const
+    {
+        return nVal - mnVal;
+    }
+
+    double operator()(bool bVal) const
+    {
+        return (double)bVal - mnVal;
+    }
+
+    svl::SharedString operator()(const svl::SharedString&) const
+    {
+        return maString;
+    }
+
+    svl::SharedString operator()(char) const
+    {
+        return maString;
+    }
+
+    bool useFunctionForEmpty() const
+    {
+        return true;
+    }
+};
+
+}
+
+void ScMatrix::SubAddOp(bool bSub, double fVal, svl::SharedString aString, ScMatrix& rMat)
+{
+    if(bSub)
+    {
+        SubOp aOp(fVal, aString);
+        pImpl->ApplyOperation(aOp, *rMat.pImpl);
+    }
+    else
+    {
+        AddOp aOp(fVal, aString);
+        pImpl->ApplyOperation(aOp, *rMat.pImpl);
+    }
+}
+
 ScMatrix& ScMatrix::operator+= ( const ScMatrix& r )
 {
     pImpl->AddValues(*r.pImpl);


More information about the Libreoffice-commits mailing list