summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorƁukasz Hryniuk <lukasz.hryniuk@wp.pl>2015-03-04 22:12:11 +0100
committerMarkus Mohrhard <markus.mohrhard@googlemail.com>2015-03-09 21:30:44 +0000
commit1c2405ba44c5a146188c19e235f857ab18ea05f0 (patch)
treed076b8f686fc8c3ef69cd1c7e42e65f1771cc788
parente96a5d4064a6002eb95b2c05f4e68c79bb766b07 (diff)
tdf#89387 General functor and basic operations
Add a functor MatOp and ScMatrix methods for scalar-matrix operations, both unary and binary. It can be used for operations which modify each element for the matrix (in constrast to accumulating ones, like ScGCD or ScAmpersand). Split method for addition and substraction into two methods for consistency and simplicity. Change-Id: Ic040233429ee120ac325d7baf31a70bba232041d Reviewed-on: https://gerrit.libreoffice.org/14749 Tested-by: Markus Mohrhard <markus.mohrhard@googlemail.com> Reviewed-by: Markus Mohrhard <markus.mohrhard@googlemail.com>
-rw-r--r--sc/inc/scmatrix.hxx8
-rw-r--r--sc/source/core/tool/interpr1.cxx26
-rw-r--r--sc/source/core/tool/interpr5.cxx55
-rw-r--r--sc/source/core/tool/scmatrix.cxx170
4 files changed, 134 insertions, 125 deletions
diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index 255d45219017..e85054e22b52 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -387,7 +387,13 @@ 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);
+ void NotOp(svl::SharedString aString, ScMatrix& rMat);
+ void NegOp(svl::SharedString aString, ScMatrix& rMat);
+ void AddOp(svl::SharedString aString, double fVal, ScMatrix& rMat);
+ void SubOp(bool bFlag, svl::SharedString aString, double fVal, ScMatrix& rMat);
+ void MulOp(svl::SharedString aString, double fVal, ScMatrix& rMat);
+ void DivOp(bool bFlag, svl::SharedString aString, double fVal, ScMatrix& rMat);
+ void PowOp(bool bFlag, svl::SharedString aString, double fVal, ScMatrix& rMat);
ScMatrix& operator+= ( const ScMatrix& r );
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 40824912f66d..e7fd64480c15 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -1500,17 +1500,8 @@ void ScInterpreter::ScNeg()
PushIllegalArgument();
else
{
- for (SCSIZE i = 0; i < nC; ++i)
- {
- for (SCSIZE j = 0; j < nR; ++j)
- {
- if ( pMat->IsValueOrEmpty(i,j) )
- pResMat->PutDouble( -pMat->GetDouble(i,j), i, j );
- else
- pResMat->PutString(
- mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE)), i, j);
- }
- }
+ svl::SharedString aString = mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE));
+ pMat->NegOp(aString, *pResMat);
PushMatrix( pResMat );
}
}
@@ -1554,17 +1545,8 @@ void ScInterpreter::ScNot()
PushIllegalArgument();
else
{
- for (SCSIZE i = 0; i < nC; ++i)
- {
- for (SCSIZE j = 0; j < nR; ++j)
- {
- if ( pMat->IsValueOrEmpty(i,j) )
- pResMat->PutDouble( double(pMat->GetDouble(i,j) == 0.0), i, j );
- else
- pResMat->PutString(
- mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE)), i, j);
- }
- }
+ svl::SharedString aString = mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE));
+ pMat->NotOp(aString, *pResMat);
PushMatrix( pResMat );
}
}
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index 38863a0b31c4..81bcdfc927da 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -1284,20 +1284,13 @@ void ScInterpreter::CalculateAddSub(bool _bSub)
if (pResMat)
{
svl::SharedString aString = mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE));
- if (bFlag || !_bSub )
+ if (_bSub)
{
- if (_bSub)
- {
- pMat->SubAddOp(true, fVal, aString, *pResMat);
- }
- else
- {
- pMat->SubAddOp(false, fVal, aString, *pResMat);
- }
+ pMat->SubOp(bFlag, aString, fVal, *pResMat);
}
else
{
- pMat->SubAddOp(false, -fVal, aString, *pResMat);
+ pMat->AddOp(aString, fVal, *pResMat);
}
PushMatrix(pResMat);
}
@@ -1476,12 +1469,8 @@ void ScInterpreter::ScMul()
ScMatrixRef pResMat = GetNewMat(nC, nR);
if (pResMat)
{
- SCSIZE nCount = nC * nR;
- for ( SCSIZE i = 0; i < nCount; i++ )
- if (pMat->IsValue(i))
- pResMat->PutDouble(pMat->GetDouble(i)*fVal, i);
- else
- pResMat->PutString(mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE)), i);
+ svl::SharedString aString = mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE));
+ pMat->MulOp(aString, fVal, *pResMat);
PushMatrix(pResMat);
}
else
@@ -1554,21 +1543,8 @@ void ScInterpreter::ScDiv()
ScMatrixRef pResMat = GetNewMat(nC, nR);
if (pResMat)
{
- SCSIZE nCount = nC * nR;
- if (bFlag)
- { for ( SCSIZE i = 0; i < nCount; i++ )
- if (pMat->IsValue(i))
- pResMat->PutDouble( div( fVal, pMat->GetDouble(i)), i);
- else
- pResMat->PutString(mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE)), i);
- }
- else
- { for ( SCSIZE i = 0; i < nCount; i++ )
- if (pMat->IsValue(i))
- pResMat->PutDouble( div( pMat->GetDouble(i), fVal), i);
- else
- pResMat->PutString(mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE)), i);
- }
+ svl::SharedString aString = mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE));
+ pMat->DivOp(bFlag, aString, fVal, *pResMat);
PushMatrix(pResMat);
}
else
@@ -1633,21 +1609,8 @@ void ScInterpreter::ScPow()
ScMatrixRef pResMat = GetNewMat(nC, nR);
if (pResMat)
{
- SCSIZE nCount = nC * nR;
- if (bFlag)
- { for ( SCSIZE i = 0; i < nCount; i++ )
- if (pMat->IsValue(i))
- pResMat->PutDouble(pow(fVal,pMat->GetDouble(i)), i);
- else
- pResMat->PutString(mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE)), i);
- }
- else
- { for ( SCSIZE i = 0; i < nCount; i++ )
- if (pMat->IsValue(i))
- pResMat->PutDouble(pow(pMat->GetDouble(i),fVal), i);
- else
- pResMat->PutString(mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE)), i);
- }
+ svl::SharedString aString = mrStrPool.intern(ScGlobal::GetRscString(STR_NO_VALUE));
+ pMat->PowOp(bFlag, aString, fVal, *pResMat);
PushMatrix(pResMat);
}
else
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 8273f44c5adc..5f6e1559b44b 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -24,6 +24,7 @@
#include "interpre.hxx"
#include "mtvelements.hxx"
#include "compare.hxx"
+#include "math.hxx"
#include <boost/noncopyable.hpp>
#include <svl/zforlist.hxx>
@@ -35,6 +36,7 @@
#include <vector>
#include <limits>
+#include <type_traits>
#include <mdds/multi_type_matrix.hpp>
#include <mdds/multi_type_vector_types.hpp>
@@ -1893,12 +1895,12 @@ struct return_type<char>
}
-template<typename T, typename U>
+template<typename T, typename U, typename return_type>
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 return_type value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef typename T::const_iterator::difference_type difference_type;
@@ -1973,7 +1975,7 @@ public:
}
};
-template<typename T, typename U>
+template<typename T, typename U, typename return_type>
struct MatrixIteratorWrapper
{
private:
@@ -1988,14 +1990,14 @@ public:
{
}
- wrapped_iterator<T, U> begin()
+ wrapped_iterator<T, U, return_type> begin()
{
- return wrapped_iterator<T, U>(m_itBegin, maOp);
+ return wrapped_iterator<T, U, return_type>(m_itBegin, maOp);
}
- wrapped_iterator<T, U> end()
+ wrapped_iterator<T, U, return_type> end()
{
- return wrapped_iterator<T, U>(m_itEnd, maOp);
+ return wrapped_iterator<T, U, return_type>(m_itEnd, maOp);
}
};
@@ -2025,7 +2027,7 @@ public:
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);
+ MatrixIteratorWrapper<block_type, T, typename T::number_value_type> aFunc(it, itEnd, maOp);
pos = mrMat.set(pos,aFunc.begin(), aFunc.end());
++pos.first;
}
@@ -2037,7 +2039,7 @@ public:
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);
+ MatrixIteratorWrapper<block_type, T, typename T::number_value_type> aFunc(it, itEnd, maOp);
pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
++pos.first;
}
@@ -2049,7 +2051,7 @@ public:
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);
+ MatrixIteratorWrapper<block_type, T, typename T::string_value_type> aFunc(it, itEnd, maOp);
pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
++pos.first;
}
@@ -2059,7 +2061,7 @@ public:
if (maOp.useFunctionForEmpty())
{
std::vector<char> aVec(node.size);
- MatrixIteratorWrapper<std::vector<char>, T> aFunc(aVec.begin(), aVec.end(), maOp);
+ MatrixIteratorWrapper<std::vector<char>, T, typename T::empty_value_type> aFunc(aVec.begin(), aVec.end(), maOp);
pos = mrMat.set(pos, aFunc.begin(), aFunc.end());
++pos.first;
}
@@ -2510,30 +2512,64 @@ void ScMatrix::MergeDoubleArray( std::vector<double>& rArray, Op eOp ) const
pImpl->MergeDoubleArray(rArray, eOp);
}
-namespace {
+namespace matop {
+
+/**
+ * COp struct is used in MatOp class to provide (through template specialization)
+ * different actions for empty entries in a matrix.
+ */
+template <typename T, typename S>
+struct COp {};
+
+template <typename T>
+struct COp<T, svl::SharedString>
+{
+ svl::SharedString operator()(char, T /*aOp*/, const svl::SharedString& aString) const
+ {
+ return aString;
+ }
+};
+
+template <typename T>
+struct COp<T, double>
+{
+ double operator()(char, T aOp, const svl::SharedString& /*aString*/) const
+ {
+ return aOp(double{}, double{});
+ }
+};
-struct AddOp
+template<typename TOp, typename TEmptyRes=svl::SharedString, typename TRet=double>
+struct MatOp
{
private:
- double mnVal;
+ TOp maOp;
svl::SharedString maString;
+ double mfVal;
+ bool mbUseForEmpty;
+ COp<TOp, TEmptyRes> maCOp;
public:
- AddOp(double nVal, svl::SharedString aString):
- mnVal(nVal),
- maString(aString)
- {
- }
+ typedef TEmptyRes empty_value_type;
+ typedef TRet number_value_type;
+ typedef svl::SharedString string_value_type;
+
+ MatOp(TOp op, svl::SharedString aString, double fVal=0.0, bool bUseForEmpty=true):
+ maOp(op),
+ maString(aString),
+ mfVal(fVal),
+ mbUseForEmpty(bUseForEmpty)
+ { }
- double operator()(double nVal) const
+ TRet operator()(double fVal) const
{
- return nVal + mnVal;
+ return maOp(fVal, mfVal);
}
- double operator()(bool bVal) const
+ TRet operator()(bool bVal) const
{
- return mnVal + (double)bVal;
+ return maOp((double)bVal, mfVal);
}
svl::SharedString operator()(const svl::SharedString&) const
@@ -2541,69 +2577,91 @@ public:
return maString;
}
- svl::SharedString operator()(char) const
+ TEmptyRes operator()(char) const
{
- return maString;
+ return maCOp(char{}, maOp, maString);
}
bool useFunctionForEmpty() const
{
- return true;
+ return mbUseForEmpty;
}
};
-struct SubOp
+}
+
+void ScMatrix::NotOp(svl::SharedString aString, ScMatrix& rMat)
{
-private:
- double mnVal;
- svl::SharedString maString;
+ auto not_ = [&](double a, double){return double(a == 0.0);};
+ matop::MatOp<decltype(not_), double> aOp(not_, aString);
+ pImpl->ApplyOperation(aOp, *rMat.pImpl);
+}
-public:
+void ScMatrix::NegOp(svl::SharedString aString, ScMatrix& rMat)
+{
+ auto neg_ = [&](double a, double){return -a;};
+ matop::MatOp<decltype(neg_), double> aOp(neg_, aString);
+ pImpl->ApplyOperation(aOp, *rMat.pImpl);
+}
- SubOp(double nVal, svl::SharedString aString):
- mnVal(nVal),
- maString(aString)
- {
- }
+void ScMatrix::AddOp(svl::SharedString aString, double fVal, ScMatrix& rMat)
+{
+ auto add_ = [&](double a, double b){return a + b;};
+ matop::MatOp<decltype(add_)> aOp(add_, aString, fVal);
+ pImpl->ApplyOperation(aOp, *rMat.pImpl);
+}
- double operator()(double nVal) const
+void ScMatrix::SubOp(bool bFlag, svl::SharedString aString, double fVal, ScMatrix& rMat)
+{
+ if (bFlag)
{
- return mnVal - nVal;
+ auto sub_ = [&](double a, double b){return b - a;};
+ matop::MatOp<decltype(sub_)> aOp(sub_, aString, fVal);
+ pImpl->ApplyOperation(aOp, *rMat.pImpl);
}
-
- double operator()(bool bVal) const
+ else
{
- return mnVal - (double)bVal;
+ auto sub_ = [&](double a, double b){return a - b;};
+ matop::MatOp<decltype(sub_)> aOp(sub_, aString, fVal);
+ pImpl->ApplyOperation(aOp, *rMat.pImpl);
}
+}
- svl::SharedString operator()(const svl::SharedString&) const
- {
- return maString;
- }
+void ScMatrix::MulOp(svl::SharedString aString, double fVal, ScMatrix& rMat)
+{
+ auto mul_ = [&](double a, double b){return a * b;};
+ matop::MatOp<decltype(mul_)> aOp(mul_, aString, fVal);
+ pImpl->ApplyOperation(aOp, *rMat.pImpl);
+}
- svl::SharedString operator()(char) const
+void ScMatrix::DivOp(bool bFlag, svl::SharedString aString, double fVal, ScMatrix& rMat)
+{
+ if (bFlag)
{
- return maString;
+ auto div_ = [&](double a, double b){return sc::div(b, a);};
+ matop::MatOp<decltype(div_), svl::SharedString> aOp(div_, aString, fVal);
+ pImpl->ApplyOperation(aOp, *rMat.pImpl);
}
-
- bool useFunctionForEmpty() const
+ else
{
- return true;
+ auto div_ = [&](double a, double b){return sc::div(a, b);};
+ matop::MatOp<decltype(div_), svl::SharedString> aOp(div_, aString, fVal);
+ pImpl->ApplyOperation(aOp, *rMat.pImpl);
}
-};
-
}
-void ScMatrix::SubAddOp(bool bSub, double fVal, svl::SharedString aString, ScMatrix& rMat)
+void ScMatrix::PowOp(bool bFlag, svl::SharedString aString, double fVal, ScMatrix& rMat)
{
- if(bSub)
+ if (bFlag)
{
- SubOp aOp(fVal, aString);
+ auto pow_ = [&](double a, double b){return pow(b, a);};
+ matop::MatOp<decltype(pow_)> aOp(pow_, aString, fVal);
pImpl->ApplyOperation(aOp, *rMat.pImpl);
}
else
{
- AddOp aOp(fVal, aString);
+ auto pow_ = [&](double a, double b){return pow(a, b);};
+ matop::MatOp<decltype(pow_)> aOp(pow_, aString, fVal);
pImpl->ApplyOperation(aOp, *rMat.pImpl);
}
}