sc/inc/scmatrix.hxx | 3 + sc/source/core/tool/interpr1.cxx | 65 ---------------------- sc/source/core/tool/scmatrix.cxx | 111 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 63 deletions(-)
New commits: commit c91c3d161561e6d8e43527b0211ab67de54d47cf Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Fri Jun 28 17:54:34 2013 -0400 Better to calculate max and min value of matrix *in* the matrix itself. Change-Id: I410b345ac32550a188aa356e133ef8e0e9b13d9f diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx index 66b271b..d6ac279 100644 --- a/sc/inc/scmatrix.hxx +++ b/sc/inc/scmatrix.hxx @@ -349,6 +349,9 @@ public: IterateResult Product(bool bTextAsZero) const; size_t Count(bool bCountStrings) const; + double GetMaxValue( bool bTextAsZero ) const; + double GetMinValue( bool bTextAsZero ) const; + // All other matrix functions MatMult, MInv, ... are in ScInterpreter // to be numerically safe. diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index aa55dcb..9cb89ae 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -3729,39 +3729,7 @@ void ScInterpreter::ScMin( bool bTextAsZero ) { ScMatrixRef pMat = GetMatrix(); if (pMat) - { - SCSIZE nC, nR; - nFuncFmtType = NUMBERFORMAT_NUMBER; - pMat->GetDimensions(nC, nR); - if (pMat->IsNumeric()) - { - for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++) - for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++) - { - nVal = pMat->GetDouble(nMatCol,nMatRow); - if (nMin > nVal) nMin = nVal; - } - } - else - { - for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++) - { - for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++) - { - if (!pMat->IsString(nMatCol,nMatRow)) - { - nVal = pMat->GetDouble(nMatCol,nMatRow); - if (nMin > nVal) nMin = nVal; - } - else if ( bTextAsZero ) - { - if ( nMin > 0.0 ) - nMin = 0.0; - } - } - } - } - } + nMin = pMat->GetMinValue(bTextAsZero); } break; case svString : @@ -3855,36 +3823,7 @@ void ScInterpreter::ScMax( bool bTextAsZero ) if (pMat) { nFuncFmtType = NUMBERFORMAT_NUMBER; - SCSIZE nC, nR; - pMat->GetDimensions(nC, nR); - if (pMat->IsNumeric()) - { - for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++) - for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++) - { - nVal = pMat->GetDouble(nMatCol,nMatRow); - if (nMax < nVal) nMax = nVal; - } - } - else - { - for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++) - { - for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++) - { - if (!pMat->IsString(nMatCol,nMatRow)) - { - nVal = pMat->GetDouble(nMatCol,nMatRow); - if (nMax < nVal) nMax = nVal; - } - else if ( bTextAsZero ) - { - if ( nMax < 0.0 ) - nMax = 0.0; - } - } - } - } + nMax = pMat->GetMaxValue(bTextAsZero); } } break; diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx index 26fe7d3..bf3ea63 100644 --- a/sc/source/core/tool/scmatrix.cxx +++ b/sc/source/core/tool/scmatrix.cxx @@ -223,6 +223,9 @@ public: ScMatrix::IterateResult Product(bool bTextAsZero) const; size_t Count(bool bCountStrings) const; + double GetMaxValue( bool bTextAsZero ) const; + double GetMinValue( bool bTextAsZero ) const; + #if DEBUG_MATRIX void Dump() const; #endif @@ -935,6 +938,90 @@ public: } }; +struct MaxOp +{ + static double init() { return std::numeric_limits<double>::min(); } + static double compare(double left, double right) + { + return std::max(left, right); + } + + static double boolValue( + mdds::mtv::boolean_element_block::const_iterator it, + mdds::mtv::boolean_element_block::const_iterator itEnd) + { + // If the array has at least one true value, the maximum value is 1. + it = std::find(it, itEnd, true); + return it == itEnd ? 0.0 : 1.0; + } +}; + +struct MinOp +{ + static double init() { return std::numeric_limits<double>::max(); } + static double compare(double left, double right) + { + return std::min(left, right); + } + + static double boolValue( + mdds::mtv::boolean_element_block::const_iterator it, + mdds::mtv::boolean_element_block::const_iterator itEnd) + { + // If the array has at least one false value, the minimum value is 0. + it = std::find(it, itEnd, false); + return it == itEnd ? 1.0 : 0.0; + } +}; + +template<typename _Op> +class CalcMaxMinValue : std::unary_function<MatrixImplType::element_block_type, void> +{ + double mfVal; + bool mbTextAsZero; +public: + CalcMaxMinValue( bool bTextAsZero ) : + mfVal(_Op::init()), + mbTextAsZero(bTextAsZero) {} + + double getValue() const { return mfVal; } + + void operator() (const MatrixImplType::element_block_node_type& node) + { + using namespace mdds::mtv; + + switch (node.type) + { + case mdds::mtm::element_numeric: + { + numeric_element_block::const_iterator it = numeric_element_block::begin(*node.data); + numeric_element_block::const_iterator itEnd = numeric_element_block::end(*node.data); + for (; it != itEnd; ++it) + mfVal = _Op::compare(mfVal, *it); + } + break; + case mdds::mtm::element_boolean: + { + boolean_element_block::const_iterator it = boolean_element_block::begin(*node.data); + boolean_element_block::const_iterator itEnd = boolean_element_block::end(*node.data); + double fVal = _Op::boolValue(it, itEnd); + mfVal = _Op::compare(mfVal, fVal); + } + break; + case mdds::mtm::element_string: + case mdds::mtm::element_empty: + { + // empty elements are treated as empty strings. + if (mbTextAsZero) + mfVal = _Op::compare(mfVal, 0.0); + } + break; + default: + ; + } + } +}; + } ScMatrix::IterateResult ScMatrixImpl::Sum(bool bTextAsZero) const @@ -966,6 +1053,20 @@ size_t ScMatrixImpl::Count(bool bCountStrings) const return aFunc.getCount(); } +double ScMatrixImpl::GetMaxValue( bool bTextAsZero ) const +{ + CalcMaxMinValue<MaxOp> aFunc(bTextAsZero); + maMat.walk(aFunc); + return aFunc.getValue(); +} + +double ScMatrixImpl::GetMinValue( bool bTextAsZero ) const +{ + CalcMaxMinValue<MinOp> aFunc(bTextAsZero); + maMat.walk(aFunc); + return aFunc.getValue(); +} + #if DEBUG_MATRIX void ScMatrixImpl::Dump() const { @@ -1308,6 +1409,16 @@ size_t ScMatrix::Count(bool bCountStrings) const return pImpl->Count(bCountStrings); } +double ScMatrix::GetMaxValue( bool bTextAsZero ) const +{ + return pImpl->GetMaxValue(bTextAsZero); +} + +double ScMatrix::GetMinValue( bool bTextAsZero ) const +{ + return pImpl->GetMinValue(bTextAsZero); +} + #if DEBUG_MATRIX void ScMatrix::Dump() const { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits