[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