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

Reply via email to