[Libreoffice-commits] core.git: 3 commits - sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Fri Oct 14 22:42:29 UTC 2016


 sc/source/core/inc/interpre.hxx  |   21 -
 sc/source/core/tool/interpr1.cxx |  749 +++++++++++++++++++--------------------
 2 files changed, 395 insertions(+), 375 deletions(-)

New commits:
commit 92874f2f134d28b77163a21ff5d04c5234ca65b2
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Oct 14 18:38:57 2016 -0400

    This is no longer used.
    
    Change-Id: I625a418c582b41ca324874e27900670151a9d2b2

diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index f9e91e1..fe860eb 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -106,15 +106,6 @@ enum ScIterFuncIf
     ifAVERAGEIF                         // Conditional average
 };
 
-enum ScIterFuncIfs
-{
-    ifSUMIFS,     // Multi-Conditional sum
-    ifAVERAGEIFS, // Multi-Conditional average
-    ifCOUNTIFS,   // Multi-Conditional count
-    ifMINIFS,     // Multi-Conditional minimum
-    ifMAXIFS      // Multi-Conditional maximum
-};
-
 enum ScETSType
 {
     etsAdd,
commit 3bd025ec76ba305ce5892acefc57385599dd12e1
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Oct 12 20:29:34 2016 -0400

    Remove the branching at the end of IterateParametersIfs().
    
    For (hopefully) better performance.
    
    Change-Id: I59ed454aa9ace2f945facceee14f4e25610feebf

diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 47d5afd..f9e91e1 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -39,6 +39,7 @@
 #include <map>
 #include <memory>
 #include <vector>
+#include <limits>
 
 class ScDocument;
 class SbxVariable;
@@ -62,6 +63,15 @@ struct RangeMatrix;
 struct Compare;
 struct CompareOptions;
 
+struct ParamIfsResult
+{
+    double mfSum = 0.0;
+    double mfMem = 0.0;
+    double mfCount = 0.0;
+    double mfMin = std::numeric_limits<double>::max();
+    double mfMax = std::numeric_limits<double>::min();
+};
+
 }
 
 namespace svl {
@@ -590,7 +600,7 @@ double IterateParametersIf( ScIterFuncIf );
 void ScCountIf();
 void ScSumIf();
 void ScAverageIf();
-double IterateParametersIfs( ScIterFuncIfs );
+void IterateParametersIfs( sc::ParamIfsResult& rRes );
 void ScSumIfs();
 void ScAverageIfs();
 void ScCountIfs();
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 838484e..465b04b 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -5312,7 +5312,7 @@ void ScInterpreter::ScCountIf()
     }
 }
 
-double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
+void ScInterpreter::IterateParametersIfs( sc::ParamIfsResult& rRes )
 {
     sal_uInt8 nParamCount = GetByte();
     sal_uInt8 nQueryCount = nParamCount / 2;
@@ -5321,12 +5321,6 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
     size_t nRowSize = 0;
     size_t nColSize = 0;
     double fVal = 0.0;
-    double fSum = 0.0;
-    double fMem = 0.0;
-    double fRes = 0.0;
-    double fCount = 0.0;
-    double fMin = std::numeric_limits<double>::max();
-    double fMax = std::numeric_limits<double>::min();
     short nParam = 1;
     size_t nRefInList = 0;
     SCCOL nDimensionCols = 0;
@@ -5345,7 +5339,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                 {
                     ScAddress aAdr;
                     if ( !PopDoubleRefOrSingleRef( aAdr ) )
-                        return 0;
+                        return;
 
                     ScRefCellValue aCell(*pDok, aAdr);
                     switch (aCell.meType)
@@ -5407,7 +5401,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
         }
 
         if (nGlobalError != FormulaError::NONE)
-            return 0;   // and bail out, no need to evaluate other arguments
+            return;   // and bail out, no need to evaluate other arguments
 
         // take range
         nParam = 1;
@@ -5445,7 +5439,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                     if (!pQueryMatrix)
                     {
                         SetError( FormulaError::IllegalParameter);
-                        return 0;
+                        return;
                     }
                     nCol1 = 0;
                     nRow1 = 0;
@@ -5459,12 +5453,12 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                 break;
             default:
                 SetError( FormulaError::IllegalParameter);
-                return 0;
+                return;
         }
         if ( nTab1 != nTab2 )
         {
             SetError( FormulaError::IllegalArgument);
-            return 0;
+            return;
         }
 
         // All reference ranges must be of same dimension and size.
@@ -5475,12 +5469,12 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
         if ((nDimensionCols != (nCol2 - nCol1 + 1)) || (nDimensionRows != (nRow2 - nRow1 + 1)))
         {
             SetError ( FormulaError::IllegalArgument);
-            return 0;
+            return;
         }
 
         // recalculate matrix values
         if (nGlobalError != FormulaError::NONE)
-            return 0;
+            return;
 
         // initialize temporary result matrix
         if (aResArray.empty())
@@ -5524,7 +5518,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
             if (nGlobalError != FormulaError::NONE || !pResultMatrix)
             {
                 SetError( FormulaError::IllegalParameter);
-                return 0;
+                return;
             }
 
             // result matrix is filled with boolean values.
@@ -5533,7 +5527,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
             if (aResArray.size() != aResValues.size())
             {
                 SetError( FormulaError::IllegalParameter);
-                return 0;
+                return;
             }
 
             std::vector<sal_uInt8>::iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
@@ -5560,7 +5554,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
     }
 
     if (nGlobalError != FormulaError::NONE)
-        return 0;   // bail out
+        return;   // bail out
 
     // main range - only for AVERAGEIFS, SUMIFS, MINIFS and MAXIFS
     if (nParamCount == 1)
@@ -5601,7 +5595,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                     if (!pMainMatrix)
                     {
                         SetError( FormulaError::IllegalParameter);
-                        return 0;
+                        return;
                     }
                     nMainCol1 = 0;
                     nMainRow1 = 0;
@@ -5615,23 +5609,23 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                 break;
             default:
                 SetError( FormulaError::IllegalParameter);
-                return 0;
+                return;
         }
         if ( nMainTab1 != nMainTab2 )
         {
             SetError( FormulaError::IllegalArgument);
-            return 0;
+            return;
         }
 
         // All reference ranges must be of same dimension and size.
         if ((nDimensionCols != (nMainCol2 - nMainCol1 + 1)) || (nDimensionRows != (nMainRow2 - nMainRow1 + 1)))
         {
             SetError ( FormulaError::IllegalArgument);
-            return 0;
+            return;
         }
 
         if (nGlobalError != FormulaError::NONE)
-            return 0;   // bail out
+            return;   // bail out
 
         // end-result calculation
         ScAddress aAdr;
@@ -5643,7 +5637,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
             if (aResArray.size() != aMainValues.size())
             {
                 SetError( FormulaError::IllegalArgument);
-                return 0;
+                return;
             }
 
             std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
@@ -5657,18 +5651,18 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                 if (GetDoubleErrorValue(fVal) == FormulaError::ElementNaN)
                     continue;
 
-                ++fCount;
+                ++rRes.mfCount;
                 if (bNull && fVal != 0.0)
                 {
                     bNull = false;
-                    fMem = fVal;
+                    rRes.mfMem = fVal;
                 }
                 else
-                    fSum += fVal;
-                if ( fMin > fVal )
-                    fMin = fVal;
-                if ( fMax < fVal )
-                    fMax = fVal;
+                    rRes.mfSum += fVal;
+                if ( rRes.mfMin > fVal )
+                    rRes.mfMin = fVal;
+                if ( rRes.mfMax < fVal )
+                    rRes.mfMax = fVal;
             }
         }
         else
@@ -5686,18 +5680,18 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                         if (aCell.hasNumeric())
                         {
                             fVal = GetCellValue(aAdr, aCell);
-                            ++fCount;
+                            ++rRes.mfCount;
                             if ( bNull && fVal != 0.0 )
                             {
                                 bNull = false;
-                                fMem = fVal;
+                                rRes.mfMem = fVal;
                             }
                             else
-                                fSum += fVal;
-                            if ( fMin > fVal )
-                                fMin = fVal;
-                            if ( fMax < fVal )
-                                fMax = fVal;
+                                rRes.mfSum += fVal;
+                            if ( rRes.mfMin > fVal )
+                                rRes.mfMin = fVal;
+                            if ( rRes.mfMax < fVal )
+                                rRes.mfMax = fVal;
                         }
                     }
                 }
@@ -5709,19 +5703,8 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
         std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
         for (; itRes != itResEnd; ++itRes)
             if (*itRes == nQueryCount)
-                ++fCount;
+                ++rRes.mfCount;
     }
-
-    switch( eFunc )
-    {
-        case ifSUMIFS:     fRes = ::rtl::math::approxAdd( fSum, fMem ); break;
-        case ifAVERAGEIFS: fRes = div( ::rtl::math::approxAdd( fSum, fMem ), fCount); break;
-        case ifCOUNTIFS:   fRes = fCount; break;
-        case ifMINIFS:     fRes = ( fMin < std::numeric_limits<double>::max() ? fMin : 0 ); break;
-        case ifMAXIFS:     fRes = ( fMax > std::numeric_limits<double>::min() ? fMax : 0 ); break;
-        default: ; // nothing
-    }
-    return fRes;
 }
 
 void ScInterpreter::ScSumIfs()
@@ -5734,7 +5717,9 @@ void ScInterpreter::ScSumIfs()
         return;
     }
 
-    PushDouble( IterateParametersIfs( ifSUMIFS));
+    sc::ParamIfsResult aRes;
+    IterateParametersIfs(aRes);
+    PushDouble(rtl::math::approxAdd(aRes.mfSum, aRes.mfMem));
 }
 
 void ScInterpreter::ScAverageIfs()
@@ -5747,7 +5732,9 @@ void ScInterpreter::ScAverageIfs()
         return;
     }
 
-    PushDouble( IterateParametersIfs( ifAVERAGEIFS));
+    sc::ParamIfsResult aRes;
+    IterateParametersIfs(aRes);
+    PushDouble(div(rtl::math::approxAdd(aRes.mfSum, aRes.mfMem), aRes.mfCount));
 }
 
 void ScInterpreter::ScCountIfs()
@@ -5760,7 +5747,9 @@ void ScInterpreter::ScCountIfs()
         return;
     }
 
-    PushDouble( IterateParametersIfs( ifCOUNTIFS));
+    sc::ParamIfsResult aRes;
+    IterateParametersIfs(aRes);
+    PushDouble(aRes.mfCount);
 }
 
 void ScInterpreter::ScMinIfs_MS()
@@ -5773,7 +5762,9 @@ void ScInterpreter::ScMinIfs_MS()
         return;
     }
 
-    PushDouble( IterateParametersIfs( ifMINIFS ) );
+    sc::ParamIfsResult aRes;
+    IterateParametersIfs(aRes);
+    PushDouble((aRes.mfMin < std::numeric_limits<double>::max()) ? aRes.mfMin : 0.0);
 }
 
 
@@ -5787,7 +5778,9 @@ void ScInterpreter::ScMaxIfs_MS()
         return;
     }
 
-    PushDouble( IterateParametersIfs( ifMAXIFS ) );
+    sc::ParamIfsResult aRes;
+    IterateParametersIfs(aRes);
+    PushDouble((aRes.mfMax > std::numeric_limits<double>::min()) ? aRes.mfMax : 0.0);
 }
 
 void ScInterpreter::ScLookup()
commit 19d788daff32df531d3c830dd83e198131f464db
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Oct 12 20:29:33 2016 -0400

    Do parameter count check outside of IterateParametersIfs().
    
    To reduce branching and scoping.
    
    Change-Id: I664e013f941c5b5dea44a6794ed133381cfc7b4c

diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 51e33c7..838484e 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -5317,450 +5317,476 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
     sal_uInt8 nParamCount = GetByte();
     sal_uInt8 nQueryCount = nParamCount / 2;
 
-    bool bCheck;
-    if ( eFunc == ifCOUNTIFS )
-        bCheck = (nParamCount >= 2) && (nParamCount % 2 == 0);
-    else
-        bCheck = (nParamCount >= 3) && (nParamCount % 2 == 1);
+    std::vector<sal_uInt8> aResArray;
+    size_t nRowSize = 0;
+    size_t nColSize = 0;
+    double fVal = 0.0;
+    double fSum = 0.0;
+    double fMem = 0.0;
+    double fRes = 0.0;
+    double fCount = 0.0;
+    double fMin = std::numeric_limits<double>::max();
+    double fMax = std::numeric_limits<double>::min();
+    short nParam = 1;
+    size_t nRefInList = 0;
+    SCCOL nDimensionCols = 0;
+    SCROW nDimensionRows = 0;
 
-    if ( !bCheck )
-    {
-        SetError( FormulaError::ParameterExpected);
-    }
-    else
+    while (nParamCount > 1 && nGlobalError == FormulaError::NONE)
     {
-        std::vector<sal_uInt8> aResArray;
-        size_t nRowSize = 0;
-        size_t nColSize = 0;
-        double fVal = 0.0;
-        double fSum = 0.0;
-        double fMem = 0.0;
-        double fRes = 0.0;
-        double fCount = 0.0;
-        double fMin = std::numeric_limits<double>::max();
-        double fMax = std::numeric_limits<double>::min();
-        short nParam = 1;
-        size_t nRefInList = 0;
-        SCCOL nDimensionCols = 0;
-        SCROW nDimensionRows = 0;
-
-        while (nParamCount > 1 && nGlobalError == FormulaError::NONE)
+        // take criteria
+        svl::SharedString aString;
+        fVal = 0.0;
+        bool bIsString = true;
+        switch ( GetStackType() )
         {
-            // take criteria
-            svl::SharedString aString;
-            fVal = 0.0;
-            bool bIsString = true;
-            switch ( GetStackType() )
-            {
-                case svDoubleRef :
-                case svSingleRef :
-                    {
-                        ScAddress aAdr;
-                        if ( !PopDoubleRefOrSingleRef( aAdr ) )
-                            return 0;
+            case svDoubleRef :
+            case svSingleRef :
+                {
+                    ScAddress aAdr;
+                    if ( !PopDoubleRefOrSingleRef( aAdr ) )
+                        return 0;
 
-                        ScRefCellValue aCell(*pDok, aAdr);
-                        switch (aCell.meType)
-                        {
-                            case CELLTYPE_VALUE :
-                                fVal = GetCellValue(aAdr, aCell);
-                                bIsString = false;
-                                break;
-                            case CELLTYPE_FORMULA :
-                                if (aCell.mpFormula->IsValue())
-                                {
-                                    fVal = GetCellValue(aAdr, aCell);
-                                    bIsString = false;
-                                }
-                                else
-                                    GetCellString(aString, aCell);
-                                break;
-                            case CELLTYPE_STRING :
-                            case CELLTYPE_EDIT :
-                                GetCellString(aString, aCell);
-                                break;
-                            default:
-                                fVal = 0.0;
-                                bIsString = false;
-                        }
-                    }
-                    break;
-                case svString:
-                    aString = GetString();
-                    break;
-                case svMatrix :
-                case svExternalDoubleRef:
-                    {
-                        ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, aString);
-                        bIsString = ScMatrix::IsNonValueType( nType);
-                    }
-                    break;
-                case svExternalSingleRef:
+                    ScRefCellValue aCell(*pDok, aAdr);
+                    switch (aCell.meType)
                     {
-                        ScExternalRefCache::TokenRef pToken;
-                        PopExternalSingleRef(pToken);
-                        if (nGlobalError == FormulaError::NONE)
-                        {
-                            if (pToken->GetType() == svDouble)
+                        case CELLTYPE_VALUE :
+                            fVal = GetCellValue(aAdr, aCell);
+                            bIsString = false;
+                            break;
+                        case CELLTYPE_FORMULA :
+                            if (aCell.mpFormula->IsValue())
                             {
-                                fVal = pToken->GetDouble();
+                                fVal = GetCellValue(aAdr, aCell);
                                 bIsString = false;
                             }
                             else
-                                aString = pToken->GetString();
-                        }
+                                GetCellString(aString, aCell);
+                            break;
+                        case CELLTYPE_STRING :
+                        case CELLTYPE_EDIT :
+                            GetCellString(aString, aCell);
+                            break;
+                        default:
+                            fVal = 0.0;
+                            bIsString = false;
                     }
-                    break;
-                default:
+                }
+                break;
+            case svString:
+                aString = GetString();
+                break;
+            case svMatrix :
+            case svExternalDoubleRef:
+                {
+                    ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, aString);
+                    bIsString = ScMatrix::IsNonValueType( nType);
+                }
+                break;
+            case svExternalSingleRef:
+                {
+                    ScExternalRefCache::TokenRef pToken;
+                    PopExternalSingleRef(pToken);
+                    if (nGlobalError == FormulaError::NONE)
                     {
-                        fVal = GetDouble();
-                        bIsString = false;
+                        if (pToken->GetType() == svDouble)
+                        {
+                            fVal = pToken->GetDouble();
+                            bIsString = false;
+                        }
+                        else
+                            aString = pToken->GetString();
                     }
-            }
+                }
+                break;
+            default:
+                {
+                    fVal = GetDouble();
+                    bIsString = false;
+                }
+        }
 
-            if (nGlobalError != FormulaError::NONE)
-                return 0;   // and bail out, no need to evaluate other arguments
+        if (nGlobalError != FormulaError::NONE)
+            return 0;   // and bail out, no need to evaluate other arguments
 
-            // take range
-            nParam = 1;
-            nRefInList = 0;
-            SCCOL nCol1 = 0;
-            SCROW nRow1 = 0;
-            SCTAB nTab1 = 0;
-            SCCOL nCol2 = 0;
-            SCROW nRow2 = 0;
-            SCTAB nTab2 = 0;
-            ScMatrixRef pQueryMatrix;
-            switch ( GetStackType() )
-            {
-                case svRefList :
-                    {
-                        ScRange aRange;
-                        PopDoubleRef( aRange, nParam, nRefInList);
-                        aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
-                    }
-                    break;
-                case svDoubleRef :
-                    PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
-                    break;
-                case svSingleRef :
-                    PopSingleRef( nCol1, nRow1, nTab1 );
-                    nCol2 = nCol1;
-                    nRow2 = nRow1;
-                    nTab2 = nTab1;
-                    break;
-                case svMatrix:
-                case svExternalSingleRef:
-                case svExternalDoubleRef:
+        // take range
+        nParam = 1;
+        nRefInList = 0;
+        SCCOL nCol1 = 0;
+        SCROW nRow1 = 0;
+        SCTAB nTab1 = 0;
+        SCCOL nCol2 = 0;
+        SCROW nRow2 = 0;
+        SCTAB nTab2 = 0;
+        ScMatrixRef pQueryMatrix;
+        switch ( GetStackType() )
+        {
+            case svRefList :
+                {
+                    ScRange aRange;
+                    PopDoubleRef( aRange, nParam, nRefInList);
+                    aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+                }
+                break;
+            case svDoubleRef :
+                PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+                break;
+            case svSingleRef :
+                PopSingleRef( nCol1, nRow1, nTab1 );
+                nCol2 = nCol1;
+                nRow2 = nRow1;
+                nTab2 = nTab1;
+                break;
+            case svMatrix:
+            case svExternalSingleRef:
+            case svExternalDoubleRef:
+                {
+                    pQueryMatrix = PopMatrix();
+                    if (!pQueryMatrix)
                     {
-                        pQueryMatrix = PopMatrix();
-                        if (!pQueryMatrix)
-                        {
-                            SetError( FormulaError::IllegalParameter);
-                            return 0;
-                        }
-                        nCol1 = 0;
-                        nRow1 = 0;
-                        nTab1 = 0;
-                        SCSIZE nC, nR;
-                        pQueryMatrix->GetDimensions( nC, nR);
-                        nCol2 = static_cast<SCCOL>(nC - 1);
-                        nRow2 = static_cast<SCROW>(nR - 1);
-                        nTab2 = 0;
+                        SetError( FormulaError::IllegalParameter);
+                        return 0;
                     }
-                    break;
-                default:
-                    SetError( FormulaError::IllegalParameter);
-                    return 0;
-            }
-            if ( nTab1 != nTab2 )
-            {
-                SetError( FormulaError::IllegalArgument);
+                    nCol1 = 0;
+                    nRow1 = 0;
+                    nTab1 = 0;
+                    SCSIZE nC, nR;
+                    pQueryMatrix->GetDimensions( nC, nR);
+                    nCol2 = static_cast<SCCOL>(nC - 1);
+                    nRow2 = static_cast<SCROW>(nR - 1);
+                    nTab2 = 0;
+                }
+                break;
+            default:
+                SetError( FormulaError::IllegalParameter);
                 return 0;
-            }
+        }
+        if ( nTab1 != nTab2 )
+        {
+            SetError( FormulaError::IllegalArgument);
+            return 0;
+        }
 
-            // All reference ranges must be of same dimension and size.
-            if (!nDimensionCols)
-                nDimensionCols = nCol2 - nCol1 + 1;
-            if (!nDimensionRows)
-                nDimensionRows = nRow2 - nRow1 + 1;
-            if ((nDimensionCols != (nCol2 - nCol1 + 1)) || (nDimensionRows != (nRow2 - nRow1 + 1)))
-            {
-                SetError ( FormulaError::IllegalArgument);
-                return 0;
-            }
+        // All reference ranges must be of same dimension and size.
+        if (!nDimensionCols)
+            nDimensionCols = nCol2 - nCol1 + 1;
+        if (!nDimensionRows)
+            nDimensionRows = nRow2 - nRow1 + 1;
+        if ((nDimensionCols != (nCol2 - nCol1 + 1)) || (nDimensionRows != (nRow2 - nRow1 + 1)))
+        {
+            SetError ( FormulaError::IllegalArgument);
+            return 0;
+        }
 
-            // recalculate matrix values
-            if (nGlobalError != FormulaError::NONE)
-                return 0;
+        // recalculate matrix values
+        if (nGlobalError != FormulaError::NONE)
+            return 0;
 
-            // initialize temporary result matrix
-            if (aResArray.empty())
-            {
-                nColSize = nCol2 - nCol1 + 1;
-                nRowSize = nRow2 - nRow1 + 1;
-                aResArray.resize(nColSize*nRowSize, 0);
-            }
+        // initialize temporary result matrix
+        if (aResArray.empty())
+        {
+            nColSize = nCol2 - nCol1 + 1;
+            nRowSize = nRow2 - nRow1 + 1;
+            aResArray.resize(nColSize*nRowSize, 0);
+        }
 
-            ScQueryParam rParam;
-            rParam.nRow1       = nRow1;
-            rParam.nRow2       = nRow2;
+        ScQueryParam rParam;
+        rParam.nRow1       = nRow1;
+        rParam.nRow2       = nRow2;
 
-            ScQueryEntry& rEntry = rParam.GetEntry(0);
-            ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
-            rEntry.bDoQuery = true;
-            if (!bIsString)
+        ScQueryEntry& rEntry = rParam.GetEntry(0);
+        ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
+        rEntry.bDoQuery = true;
+        if (!bIsString)
+        {
+            rItem.meType = ScQueryEntry::ByValue;
+            rItem.mfVal = fVal;
+            rEntry.eOp = SC_EQUAL;
+        }
+        else
+        {
+            rParam.FillInExcelSyntax(pDok->GetSharedStringPool(), aString.getString(), 0, pFormatter);
+            if (rItem.meType == ScQueryEntry::ByString)
+                rParam.eSearchType = DetectSearchType(rItem.maString.getString(), pDok);
+        }
+        ScAddress aAdr;
+        aAdr.SetTab( nTab1 );
+        rParam.nCol1  = nCol1;
+        rParam.nCol2  = nCol2;
+        rEntry.nField = nCol1;
+        SCsCOL nColDiff = -nCol1;
+        SCsROW nRowDiff = -nRow1;
+        if (pQueryMatrix)
+        {
+            // Never case-sensitive.
+            sc::CompareOptions aOptions( pDok, rEntry, rParam.eSearchType);
+            ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
+            if (nGlobalError != FormulaError::NONE || !pResultMatrix)
             {
-                rItem.meType = ScQueryEntry::ByValue;
-                rItem.mfVal = fVal;
-                rEntry.eOp = SC_EQUAL;
+                SetError( FormulaError::IllegalParameter);
+                return 0;
             }
-            else
+
+            // result matrix is filled with boolean values.
+            std::vector<double> aResValues;
+            pResultMatrix->GetDoubleArray(aResValues);
+            if (aResArray.size() != aResValues.size())
             {
-                rParam.FillInExcelSyntax(pDok->GetSharedStringPool(), aString.getString(), 0, pFormatter);
-                if (rItem.meType == ScQueryEntry::ByString)
-                    rParam.eSearchType = DetectSearchType(rItem.maString.getString(), pDok);
+                SetError( FormulaError::IllegalParameter);
+                return 0;
             }
-            ScAddress aAdr;
-            aAdr.SetTab( nTab1 );
-            rParam.nCol1  = nCol1;
-            rParam.nCol2  = nCol2;
-            rEntry.nField = nCol1;
-            SCsCOL nColDiff = -nCol1;
-            SCsROW nRowDiff = -nRow1;
-            if (pQueryMatrix)
+
+            std::vector<sal_uInt8>::iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
+            std::vector<double>::const_iterator itThisRes = aResValues.begin();
+            for (; itRes != itResEnd; ++itRes, ++itThisRes)
+                *itRes += *itThisRes;
+        }
+        else
+        {
+            ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false);
+            // Increment Entry.nField in iterator when switching to next column.
+            aCellIter.SetAdvanceQueryParamEntryField( true );
+            if ( aCellIter.GetFirst() )
             {
-                // Never case-sensitive.
-                sc::CompareOptions aOptions( pDok, rEntry, rParam.eSearchType);
-                ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
-                if (nGlobalError != FormulaError::NONE || !pResultMatrix)
+                do
                 {
-                    SetError( FormulaError::IllegalParameter);
-                    return 0;
-                }
+                    size_t nC = aCellIter.GetCol() + nColDiff;
+                    size_t nR = aCellIter.GetRow() + nRowDiff;
+                    ++aResArray[nC*nRowSize+nR];
+                } while ( aCellIter.GetNext() );
+            }
+        }
+        nParamCount -= 2;
+    }
 
-                // result matrix is filled with boolean values.
-                std::vector<double> aResValues;
-                pResultMatrix->GetDoubleArray(aResValues);
-                if (aResArray.size() != aResValues.size())
+    if (nGlobalError != FormulaError::NONE)
+        return 0;   // bail out
+
+    // main range - only for AVERAGEIFS, SUMIFS, MINIFS and MAXIFS
+    if (nParamCount == 1)
+    {
+        nParam = 1;
+        nRefInList = 0;
+        bool bNull = true;
+        SCCOL nMainCol1 = 0;
+        SCROW nMainRow1 = 0;
+        SCTAB nMainTab1 = 0;
+        SCCOL nMainCol2 = 0;
+        SCROW nMainRow2 = 0;
+        SCTAB nMainTab2 = 0;
+        ScMatrixRef pMainMatrix;
+        switch ( GetStackType() )
+        {
+            case svRefList :
                 {
-                    SetError( FormulaError::IllegalParameter);
-                    return 0;
+                    ScRange aRange;
+                    PopDoubleRef( aRange, nParam, nRefInList);
+                    aRange.GetVars( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2);
                 }
-
-                std::vector<sal_uInt8>::iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
-                std::vector<double>::const_iterator itThisRes = aResValues.begin();
-                for (; itRes != itResEnd; ++itRes, ++itThisRes)
-                    *itRes += *itThisRes;
-            }
-            else
-            {
-                ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false);
-                // Increment Entry.nField in iterator when switching to next column.
-                aCellIter.SetAdvanceQueryParamEntryField( true );
-                if ( aCellIter.GetFirst() )
+                break;
+            case svDoubleRef :
+                PopDoubleRef( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2 );
+                break;
+            case svSingleRef :
+                PopSingleRef( nMainCol1, nMainRow1, nMainTab1 );
+                nMainCol2 = nMainCol1;
+                nMainRow2 = nMainRow1;
+                nMainTab2 = nMainTab1;
+                break;
+            case svMatrix:
+            case svExternalSingleRef:
+            case svExternalDoubleRef:
                 {
-                    do
+                    pMainMatrix = PopMatrix();
+                    if (!pMainMatrix)
                     {
-                        size_t nC = aCellIter.GetCol() + nColDiff;
-                        size_t nR = aCellIter.GetRow() + nRowDiff;
-                        ++aResArray[nC*nRowSize+nR];
-                    } while ( aCellIter.GetNext() );
+                        SetError( FormulaError::IllegalParameter);
+                        return 0;
+                    }
+                    nMainCol1 = 0;
+                    nMainRow1 = 0;
+                    nMainTab1 = 0;
+                    SCSIZE nC, nR;
+                    pMainMatrix->GetDimensions( nC, nR);
+                    nMainCol2 = static_cast<SCCOL>(nC - 1);
+                    nMainRow2 = static_cast<SCROW>(nR - 1);
+                    nMainTab2 = 0;
                 }
-            }
-            nParamCount -= 2;
+                break;
+            default:
+                SetError( FormulaError::IllegalParameter);
+                return 0;
+        }
+        if ( nMainTab1 != nMainTab2 )
+        {
+            SetError( FormulaError::IllegalArgument);
+            return 0;
+        }
+
+        // All reference ranges must be of same dimension and size.
+        if ((nDimensionCols != (nMainCol2 - nMainCol1 + 1)) || (nDimensionRows != (nMainRow2 - nMainRow1 + 1)))
+        {
+            SetError ( FormulaError::IllegalArgument);
+            return 0;
         }
 
         if (nGlobalError != FormulaError::NONE)
             return 0;   // bail out
 
-        // main range - only for AVERAGEIFS, SUMIFS, MINIFS and MAXIFS
-        if (nParamCount == 1)
+        // end-result calculation
+        ScAddress aAdr;
+        aAdr.SetTab( nMainTab1 );
+        if (pMainMatrix)
         {
-            nParam = 1;
-            nRefInList = 0;
-            bool bNull = true;
-            SCCOL nMainCol1 = 0;
-            SCROW nMainRow1 = 0;
-            SCTAB nMainTab1 = 0;
-            SCCOL nMainCol2 = 0;
-            SCROW nMainRow2 = 0;
-            SCTAB nMainTab2 = 0;
-            ScMatrixRef pMainMatrix;
-            switch ( GetStackType() )
-            {
-                case svRefList :
-                    {
-                        ScRange aRange;
-                        PopDoubleRef( aRange, nParam, nRefInList);
-                        aRange.GetVars( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2);
-                    }
-                    break;
-                case svDoubleRef :
-                    PopDoubleRef( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2 );
-                    break;
-                case svSingleRef :
-                    PopSingleRef( nMainCol1, nMainRow1, nMainTab1 );
-                    nMainCol2 = nMainCol1;
-                    nMainRow2 = nMainRow1;
-                    nMainTab2 = nMainTab1;
-                    break;
-                case svMatrix:
-                case svExternalSingleRef:
-                case svExternalDoubleRef:
-                    {
-                        pMainMatrix = PopMatrix();
-                        if (!pMainMatrix)
-                        {
-                            SetError( FormulaError::IllegalParameter);
-                            return 0;
-                        }
-                        nMainCol1 = 0;
-                        nMainRow1 = 0;
-                        nMainTab1 = 0;
-                        SCSIZE nC, nR;
-                        pMainMatrix->GetDimensions( nC, nR);
-                        nMainCol2 = static_cast<SCCOL>(nC - 1);
-                        nMainRow2 = static_cast<SCROW>(nR - 1);
-                        nMainTab2 = 0;
-                    }
-                    break;
-                default:
-                    SetError( FormulaError::IllegalParameter);
-                    return 0;
-            }
-            if ( nMainTab1 != nMainTab2 )
+            std::vector<double> aMainValues;
+            pMainMatrix->GetDoubleArray(aMainValues, false); // Map empty values to NaN's.
+            if (aResArray.size() != aMainValues.size())
             {
                 SetError( FormulaError::IllegalArgument);
                 return 0;
             }
 
-            // All reference ranges must be of same dimension and size.
-            if ((nDimensionCols != (nMainCol2 - nMainCol1 + 1)) || (nDimensionRows != (nMainRow2 - nMainRow1 + 1)))
+            std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
+            std::vector<double>::const_iterator itMain = aMainValues.begin();
+            for (; itRes != itResEnd; ++itRes, ++itMain)
             {
-                SetError ( FormulaError::IllegalArgument);
-                return 0;
-            }
-
-            if (nGlobalError != FormulaError::NONE)
-                return 0;   // bail out
+                if (*itRes != nQueryCount)
+                    continue;
 
-            // end-result calculation
-            ScAddress aAdr;
-            aAdr.SetTab( nMainTab1 );
-            if (pMainMatrix)
-            {
-                std::vector<double> aMainValues;
-                pMainMatrix->GetDoubleArray(aMainValues, false); // Map empty values to NaN's.
-                if (aResArray.size() != aMainValues.size())
-                {
-                    SetError( FormulaError::IllegalArgument);
-                    return 0;
-                }
+                fVal = *itMain;
+                if (GetDoubleErrorValue(fVal) == FormulaError::ElementNaN)
+                    continue;
 
-                std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
-                std::vector<double>::const_iterator itMain = aMainValues.begin();
-                for (; itRes != itResEnd; ++itRes, ++itMain)
+                ++fCount;
+                if (bNull && fVal != 0.0)
                 {
-                    if (*itRes != nQueryCount)
-                        continue;
-
-                    fVal = *itMain;
-                    if (GetDoubleErrorValue(fVal) == FormulaError::ElementNaN)
-                        continue;
-
-                    ++fCount;
-                    if (bNull && fVal != 0.0)
-                    {
-                        bNull = false;
-                        fMem = fVal;
-                    }
-                    else
-                        fSum += fVal;
-                    if ( fMin > fVal )
-                        fMin = fVal;
-                    if ( fMax < fVal )
-                        fMax = fVal;
+                    bNull = false;
+                    fMem = fVal;
                 }
+                else
+                    fSum += fVal;
+                if ( fMin > fVal )
+                    fMin = fVal;
+                if ( fMax < fVal )
+                    fMax = fVal;
             }
-            else
+        }
+        else
+        {
+            std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin();
+            for (size_t nCol = 0; nCol < nColSize; ++nCol)
             {
-                std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin();
-                for (size_t nCol = 0; nCol < nColSize; ++nCol)
+                for (size_t nRow = 0; nRow < nRowSize; ++nRow, ++itRes)
                 {
-                    for (size_t nRow = 0; nRow < nRowSize; ++nRow, ++itRes)
+                    if (*itRes == nQueryCount)
                     {
-                        if (*itRes == nQueryCount)
+                        aAdr.SetCol( static_cast<SCCOL>(nCol) + nMainCol1);
+                        aAdr.SetRow( static_cast<SCROW>(nRow) + nMainRow1);
+                        ScRefCellValue aCell(*pDok, aAdr);
+                        if (aCell.hasNumeric())
                         {
-                            aAdr.SetCol( static_cast<SCCOL>(nCol) + nMainCol1);
-                            aAdr.SetRow( static_cast<SCROW>(nRow) + nMainRow1);
-                            ScRefCellValue aCell(*pDok, aAdr);
-                            if (aCell.hasNumeric())
+                            fVal = GetCellValue(aAdr, aCell);
+                            ++fCount;
+                            if ( bNull && fVal != 0.0 )
                             {
-                                fVal = GetCellValue(aAdr, aCell);
-                                ++fCount;
-                                if ( bNull && fVal != 0.0 )
-                                {
-                                    bNull = false;
-                                    fMem = fVal;
-                                }
-                                else
-                                    fSum += fVal;
-                                if ( fMin > fVal )
-                                    fMin = fVal;
-                                if ( fMax < fVal )
-                                    fMax = fVal;
+                                bNull = false;
+                                fMem = fVal;
                             }
+                            else
+                                fSum += fVal;
+                            if ( fMin > fVal )
+                                fMin = fVal;
+                            if ( fMax < fVal )
+                                fMax = fVal;
                         }
                     }
                 }
             }
         }
-        else
-        {
-            std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
-            for (; itRes != itResEnd; ++itRes)
-                if (*itRes == nQueryCount)
-                    ++fCount;
-        }
+    }
+    else
+    {
+        std::vector<sal_uInt8>::const_iterator itRes = aResArray.begin(), itResEnd = aResArray.end();
+        for (; itRes != itResEnd; ++itRes)
+            if (*itRes == nQueryCount)
+                ++fCount;
+    }
 
-        switch( eFunc )
-        {
-            case ifSUMIFS:     fRes = ::rtl::math::approxAdd( fSum, fMem ); break;
-            case ifAVERAGEIFS: fRes = div( ::rtl::math::approxAdd( fSum, fMem ), fCount); break;
-            case ifCOUNTIFS:   fRes = fCount; break;
-            case ifMINIFS:     fRes = ( fMin < std::numeric_limits<double>::max() ? fMin : 0 ); break;
-            case ifMAXIFS:     fRes = ( fMax > std::numeric_limits<double>::min() ? fMax : 0 ); break;
-            default: ; // nothing
-        }
-        return fRes;
+    switch( eFunc )
+    {
+        case ifSUMIFS:     fRes = ::rtl::math::approxAdd( fSum, fMem ); break;
+        case ifAVERAGEIFS: fRes = div( ::rtl::math::approxAdd( fSum, fMem ), fCount); break;
+        case ifCOUNTIFS:   fRes = fCount; break;
+        case ifMINIFS:     fRes = ( fMin < std::numeric_limits<double>::max() ? fMin : 0 ); break;
+        case ifMAXIFS:     fRes = ( fMax > std::numeric_limits<double>::min() ? fMax : 0 ); break;
+        default: ; // nothing
     }
-    return 0;
+    return fRes;
 }
 
 void ScInterpreter::ScSumIfs()
 {
+    sal_uInt8 nParamCount = GetByte();
+
+    if (nParamCount < 3 || (nParamCount % 2 != 1))
+    {
+        SetError( FormulaError::ParameterExpected);
+        return;
+    }
+
     PushDouble( IterateParametersIfs( ifSUMIFS));
 }
 
 void ScInterpreter::ScAverageIfs()
 {
+    sal_uInt8 nParamCount = GetByte();
+
+    if (nParamCount < 3 || (nParamCount % 2 != 1))
+    {
+        SetError( FormulaError::ParameterExpected);
+        return;
+    }
+
     PushDouble( IterateParametersIfs( ifAVERAGEIFS));
 }
 
 void ScInterpreter::ScCountIfs()
 {
+    sal_uInt8 nParamCount = GetByte();
+
+    if (nParamCount < 2 || (nParamCount % 2 != 0))
+    {
+        SetError( FormulaError::ParameterExpected);
+        return;
+    }
+
     PushDouble( IterateParametersIfs( ifCOUNTIFS));
 }
 
 void ScInterpreter::ScMinIfs_MS()
 {
+    sal_uInt8 nParamCount = GetByte();
+
+    if (nParamCount < 3 || (nParamCount % 2 != 1))
+    {
+        SetError( FormulaError::ParameterExpected);
+        return;
+    }
+
     PushDouble( IterateParametersIfs( ifMINIFS ) );
 }
 
 
 void ScInterpreter::ScMaxIfs_MS()
 {
+    sal_uInt8 nParamCount = GetByte();
+
+    if (nParamCount < 3 || (nParamCount % 2 != 1))
+    {
+        SetError( FormulaError::ParameterExpected);
+        return;
+    }
+
     PushDouble( IterateParametersIfs( ifMAXIFS ) );
 }
 


More information about the Libreoffice-commits mailing list