diff options
author | Markus Mohrhard <markus.mohrhard@collabora.co.uk> | 2014-12-22 00:14:35 +0100 |
---|---|---|
committer | Markus Mohrhard <markus.mohrhard@collabora.co.uk> | 2014-12-22 01:43:48 +0100 |
commit | 3d6cedd70b3c79b3ebb65c2662df420a8acb0818 (patch) | |
tree | ce37900d5367ad0c17ad179ff4e8f9872c64980e | |
parent | 52474424f3672a052e8a90b5e8e584c32fdacfbe (diff) |
improve performance of some matrix operations, related fdo#83187
Change-Id: I0e6816a7f0d2dc051dff6a462724cb4a3c155289
-rw-r--r-- | sc/inc/scmatrix.hxx | 2 | ||||
-rw-r--r-- | sc/source/core/tool/interpr5.cxx | 26 | ||||
-rw-r--r-- | sc/source/core/tool/scmatrix.cxx | 309 |
3 files changed, 324 insertions, 13 deletions
diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx index 1e4c74ff99b3..a5117bee3278 100644 --- a/sc/inc/scmatrix.hxx +++ b/sc/inc/scmatrix.hxx @@ -379,6 +379,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 e7b8b658c15c..533aafbb51be 100644 --- a/sc/source/core/tool/interpr5.cxx +++ b/sc/source/core/tool/interpr5.cxx @@ -1188,6 +1188,11 @@ void ScInterpreter::ScAdd() { CalculateAddSub(false); } + +namespace { + +} + void ScInterpreter::CalculateAddSub(bool _bSub) { ScMatrixRef pMat1 = NULL; @@ -1278,26 +1283,21 @@ void ScInterpreter::CalculateAddSub(bool _bSub) ScMatrixRef pResMat = GetNewMat(nC, nR); 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 (_bSub) { - 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(true, fVal, aString, *pResMat); + } + else + { + pMat->SubAddOp(false, 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 5b6ccbebbb05..7594025c489a 100644 --- a/sc/source/core/tool/scmatrix.cxx +++ b/sc/source/core/tool/scmatrix.cxx @@ -286,6 +286,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 @@ -1821,6 +1824,214 @@ 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_), + 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); + rMat.maMat.walk(aFunc); +} + #if DEBUG_MATRIX void ScMatrixImpl::Dump() const { @@ -2236,6 +2447,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 mnVal - (double)bVal; + } + + 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); |