summaryrefslogtreecommitdiff
path: root/sc/source/core/tool/scmatrix.cxx
diff options
context:
space:
mode:
authorMarkus Mohrhard <markus.mohrhard@collabora.co.uk>2014-12-22 00:14:35 +0100
committerEike Rathke <erack@redhat.com>2015-01-08 00:53:18 +0000
commit4f29a7766edd19757a8ab2e38bf7fdff36c704b7 (patch)
treef18217a419fda1647da6c8d2c40ba49d16b3d7bb /sc/source/core/tool/scmatrix.cxx
parentea6da165da50c60fcf5d4dc4ab93b798f03879c8 (diff)
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@redhat.com> Tested-by: Eike Rathke <erack@redhat.com>
Diffstat (limited to 'sc/source/core/tool/scmatrix.cxx')
-rw-r--r--sc/source/core/tool/scmatrix.cxx310
1 files changed, 310 insertions, 0 deletions
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 429fd5faee04..b111ddf2d652 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);