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

Michael Meeks michael.meeks at suse.com
Tue Jul 2 20:17:23 PDT 2013


 sc/inc/column.hxx                    |    3 
 sc/inc/formulacell.hxx               |   11 
 sc/inc/formulagroup.hxx              |    5 
 sc/inc/types.hxx                     |    7 
 sc/source/core/data/column.cxx       |   74 ---
 sc/source/core/data/column2.cxx      |   20 
 sc/source/core/data/formulacell.cxx  |   40 +
 sc/source/core/tool/formulagroup.cxx |   72 ++-
 sc/source/core/tool/interpr1.cxx     |  767 --------------------------------
 sc/source/core/tool/interpr6.cxx     |  836 ++++++++++++++++++++++++++++++++++-
 10 files changed, 965 insertions(+), 870 deletions(-)

New commits:
commit b81d130626c20b806fc8a28524b38756eebc6c46
Author: Michael Meeks <michael.meeks at suse.com>
Date:   Tue Jul 2 22:01:01 2013 +0100

    Dummy formula group interpreter for testing.

diff --git a/sc/inc/formulagroup.hxx b/sc/inc/formulagroup.hxx
index 1c573c4..e645968 100644
--- a/sc/inc/formulagroup.hxx
+++ b/sc/inc/formulagroup.hxx
@@ -30,9 +30,8 @@ struct FormulaGroupContext : boost::noncopyable
 };
 
 /**
- * All the vectorized formula calculation code should be collected here.
- *
- * Abstract base class for formula group interpreters, and a factory.
+ * Abstract base class for vectorised formula group interpreters,
+ * plus a global instance factory.
  */
 class SC_DLLPUBLIC FormulaGroupInterpreter
 {
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index b20b437..b4fd646 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -20,6 +20,8 @@
 
 #include <vector>
 
+#define USE_DUMMY_INTERPRETER 1
+
 namespace sc {
 
 ScMatrixRef FormulaGroupInterpreterSoftware::inverseMatrix(const ScMatrix& /*rMat*/)
@@ -108,14 +110,61 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
 namespace opencl {
     extern sc::FormulaGroupInterpreter *createFormulaGroupInterpreter();
 }
-
 FormulaGroupInterpreter *FormulaGroupInterpreter::msInstance = NULL;
 
+#if USE_DUMMY_INTERPRETER
+class FormulaGroupInterpreterDummy : public FormulaGroupInterpreter
+{
+    enum Mode {
+        WRITE_OUTPUT = 0
+    };
+    Mode meMode;
+public:
+    FormulaGroupInterpreterDummy()
+    {
+        const char *pValue = getenv("FORMULA_GROUP_DUMMY");
+        meMode = static_cast<Mode>(OString(pValue, strlen(pValue)).toInt32());
+        fprintf(stderr, "Using Dummy Formula Group interpreter mode %d\n", (int)meMode);
+    }
+
+    virtual ScMatrixRef inverseMatrix(const ScMatrix& /*rMat*/)
+    {
+        return ScMatrixRef();
+    }
+
+    virtual bool interpret(ScDocument& rDoc, const ScAddress& rTopPos,
+                           const ScFormulaCellGroupRef& xGroup,
+                           ScTokenArray& rCode)
+    {
+        (void)rCode;
+
+        // Write simple data back into the sheet
+        if (meMode == WRITE_OUTPUT)
+        {
+            double *pDoubles = new double[xGroup->mnLength];
+            for (sal_Int32 i = 0; i < xGroup->mnLength; i++)
+                pDoubles[i] = 42.0 + i;
+            rDoc.SetFormulaResults(rTopPos, pDoubles, xGroup->mnLength);
+            delete [] pDoubles;
+        }
+        return true;
+    }
+};
+#endif
+
 /// load and/or configure the correct formula group interpreter
 FormulaGroupInterpreter *FormulaGroupInterpreter::getStatic()
 {
     static bool bOpenCLEnabled = false;
 
+#if USE_DUMMY_INTERPRETER
+    if (getenv("FORMULA_GROUP_DUMMY"))
+    {
+        delete msInstance;
+        return msInstance = new sc::FormulaGroupInterpreterDummy();
+    }
+#endif
+
     if ( msInstance &&
          bOpenCLEnabled != ScInterpreter::GetGlobalConfig().mbOpenCLEnabled )
     {
commit 1eb0aac39f366caf497534de00fb30b84ac1ba62
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 2 22:23:56 2013 -0400

    Forgot to remove these debug statements.
    
    Change-Id: I680750c43dce4b6e7f9b9ed0a6b8550bdf485a8c

diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 132ed5c..f8928e5 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -3115,12 +3115,8 @@ bool ScFormulaCell::InterpretFormulaGroup()
     if (!xGroup || !pCode)
         return false;
 
-    fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup:   calc state = %d\n", xGroup->meCalcState);
     if (xGroup->meCalcState == sc::GroupCalcDisabled)
-    {
-        fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup:   group calc disabled.\n");
         return false;
-    }
 
     switch (pCode->GetVectorState())
     {
@@ -3145,7 +3141,6 @@ bool ScFormulaCell::InterpretFormulaGroup()
     GroupTokenConverter aConverter(aCxt, aCode, *pDocument, *this, aTopPos);
     if (!aConverter.convert(*pCode))
     {
-        fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup:   disabling group calc due to failed conversion\n");
         xGroup->meCalcState = sc::GroupCalcDisabled;
         return false;
     }
@@ -3153,7 +3148,6 @@ bool ScFormulaCell::InterpretFormulaGroup()
     xGroup->meCalcState = sc::GroupCalcRunning;
     if (!sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, aTopPos, xGroup, aCode))
     {
-        fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup:   disabling group calc due to failed calculation\n");
         xGroup->meCalcState = sc::GroupCalcDisabled;
         return false;
     }
commit ce7a2d39efc66ae682873a96030332b38ba3a4d6
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 2 22:10:25 2013 -0400

    Detect circular dependency in formula groups to fallback to cell-based.
    
    Change-Id: Icfb4fd4be4e0c1f6f450fb8ddce57c7b79568e6f

diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 52a1474..07b726a 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -24,6 +24,7 @@
 
 #include "formula/tokenarray.hxx"
 #include "svl/listener.hxx"
+#include "types.hxx"
 
 #include <set>
 
@@ -40,19 +41,23 @@ struct ScSimilarFormulaDelta;
 
 struct SC_DLLPUBLIC ScFormulaCellGroup
 {
-    sal_Int32 mnRefCount;
+    mutable size_t mnRefCount;
+
     SCROW mnStart;  // Start offset of that cell
     SCROW mnLength; // How many of these do we have ?
     bool mbInvariant;
+    sc::GroupCalcState meCalcState;
 
     ScFormulaCellGroup();
     ~ScFormulaCellGroup();
 };
-inline void intrusive_ptr_add_ref(ScFormulaCellGroup *p)
+
+inline void intrusive_ptr_add_ref(const ScFormulaCellGroup *p)
 {
     p->mnRefCount++;
 }
-inline void intrusive_ptr_release(ScFormulaCellGroup *p)
+
+inline void intrusive_ptr_release(const ScFormulaCellGroup *p)
 {
     if( --p->mnRefCount == 0 )
         delete p;
diff --git a/sc/inc/types.hxx b/sc/inc/types.hxx
index 445311e..5c11da5 100644
--- a/sc/inc/types.hxx
+++ b/sc/inc/types.hxx
@@ -56,6 +56,13 @@ const sal_uInt16 MatrixEdgeTop     = 8;
 const sal_uInt16 MatrixEdgeRight   = 16;
 const sal_uInt16 MatrixEdgeOpen    = 32;
 
+enum GroupCalcState
+{
+    GroupCalcEnabled,
+    GroupCalcRunning,
+    GroupCalcDisabled
+};
+
 }
 
 #endif
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 4becbb7..82daadf 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -2166,10 +2166,15 @@ bool appendDouble(
                     nLenRemain = 0;
                 }
 
+                sal_uInt16 nErr;
+                double fVal;
                 for (; itData != itDataEnd; ++itData)
                 {
                     ScFormulaCell& rFC = **itData;
-                    rArray.push_back(rFC.GetValue());
+                    if (!rFC.GetErrorOrValue(nErr, fVal) || nErr)
+                        return false;
+
+                    rArray.push_back(fVal);
                 }
             }
             break;
@@ -2238,6 +2243,9 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
         break;
         case sc::element_type_formula:
         {
+            sal_uInt16 nErr;
+            double fVal;
+
             rCxt.maArrays.push_back(new sc::FormulaGroupContext::DoubleArrayType);
             sc::FormulaGroupContext::DoubleArrayType& rArray = rCxt.maArrays.back();
             rArray.reserve(nLenRequested);
@@ -2252,7 +2260,10 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
                 for (; it != itEnd; ++it)
                 {
                     ScFormulaCell& rCell = **it;
-                    rArray.push_back(rCell.GetValue()); // the cell may be interpreted.
+                    if (!rCell.GetErrorOrValue(nErr, fVal) || nErr)
+                        return NULL;
+
+                    rArray.push_back(fVal);
                 }
 
                 return &rArray[0];
@@ -2264,7 +2275,10 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
             for (; it != itEnd; ++it)
             {
                 ScFormulaCell& rCell = **it;
-                rArray.push_back(rCell.GetValue()); // the cell may be interpreted.
+                if (!rCell.GetErrorOrValue(nErr, fVal) || nErr)
+                    return NULL;
+
+                rArray.push_back(fVal);
             }
 
             // Fill the remaining array with values from the following blocks.
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index a129726..132ed5c 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -382,7 +382,11 @@ void adjustDBRange(ScToken* pToken, ScDocument& rNewDoc, const ScDocument* pOldD
 }
 
 ScFormulaCellGroup::ScFormulaCellGroup() :
-    mnRefCount(0), mnStart(0), mnLength(0), mbInvariant(false)
+    mnRefCount(0),
+    mnStart(0),
+    mnLength(0),
+    mbInvariant(false),
+    meCalcState(sc::GroupCalcEnabled)
 {
 }
 
@@ -1547,6 +1551,9 @@ void ScFormulaCell::SetDirty( bool bDirtyFlag )
 void ScFormulaCell::SetDirtyVar()
 {
     bDirty = true;
+    if (xGroup)
+        xGroup->meCalcState = sc::GroupCalcEnabled;
+
     // mark the sheet of this cell to be calculated
     //#FIXME do we need to revert this remnant of old fake vba events? pDocument->AddCalculateTable( aPos.Tab() );
 }
@@ -1611,7 +1618,7 @@ void ScFormulaCell::SetErrCode( sal_uInt16 n )
 void ScFormulaCell::AddRecalcMode( ScRecalcMode nBits )
 {
     if ( (nBits & RECALCMODE_EMASK) != RECALCMODE_NORMAL )
-        bDirty = true;
+        SetDirtyVar();
     if ( nBits & RECALCMODE_ONLOAD_ONCE )
     {   // OnLoadOnce nur zum Dirty setzen nach Filter-Import
         nBits = (nBits & ~RECALCMODE_EMASK) | RECALCMODE_NORMAL;
@@ -2959,9 +2966,10 @@ class GroupTokenConverter
     ScTokenArray& mrGroupTokens;
     ScDocument& mrDoc;
     ScFormulaCell& mrCell;
+    const ScAddress& mrPos;
 public:
-    GroupTokenConverter(sc::FormulaGroupContext& rCxt, ScTokenArray& rGroupTokens, ScDocument& rDoc, ScFormulaCell& rCell) :
-        mrCxt(rCxt), mrGroupTokens(rGroupTokens), mrDoc(rDoc), mrCell(rCell) {}
+    GroupTokenConverter(sc::FormulaGroupContext& rCxt, ScTokenArray& rGroupTokens, ScDocument& rDoc, ScFormulaCell& rCell, const ScAddress& rPos) :
+        mrCxt(rCxt), mrGroupTokens(rGroupTokens), mrDoc(rDoc), mrCell(rCell), mrPos(rPos) {}
 
     bool convert(ScTokenArray& rCode)
     {
@@ -2979,8 +2987,7 @@ public:
                 case svSingleRef:
                 {
                     ScSingleRefData aRef = pToken->GetSingleRef();
-                    aRef.CalcAbsIfRel(mrCell.aPos);
-                    ScAddress aRefPos(aRef.nCol, aRef.nRow, aRef.nTab);
+                    ScAddress aRefPos = aRef.toAbs(mrPos);
                     if (aRef.IsRowRel())
                     {
                         // Fetch double array guarantees that the length of the
@@ -3108,6 +3115,13 @@ bool ScFormulaCell::InterpretFormulaGroup()
     if (!xGroup || !pCode)
         return false;
 
+    fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup:   calc state = %d\n", xGroup->meCalcState);
+    if (xGroup->meCalcState == sc::GroupCalcDisabled)
+    {
+        fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup:   group calc disabled.\n");
+        return false;
+    }
+
     switch (pCode->GetVectorState())
     {
         case FormulaVectorEnabled:
@@ -3126,10 +3140,26 @@ bool ScFormulaCell::InterpretFormulaGroup()
 
     sc::FormulaGroupContext aCxt;
     ScTokenArray aCode;
-    GroupTokenConverter aConverter(aCxt, aCode, *pDocument, *this);
+    ScAddress aTopPos = aPos;
+    aTopPos.SetRow(xGroup->mnStart);
+    GroupTokenConverter aConverter(aCxt, aCode, *pDocument, *this, aTopPos);
     if (!aConverter.convert(*pCode))
+    {
+        fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup:   disabling group calc due to failed conversion\n");
+        xGroup->meCalcState = sc::GroupCalcDisabled;
+        return false;
+    }
+
+    xGroup->meCalcState = sc::GroupCalcRunning;
+    if (!sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, aTopPos, xGroup, aCode))
+    {
+        fprintf(stdout, "ScFormulaCell::InterpretFormulaGroup:   disabling group calc due to failed calculation\n");
+        xGroup->meCalcState = sc::GroupCalcDisabled;
         return false;
-    return sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, aPos, xGroup, aCode);
+    }
+
+    xGroup->meCalcState = sc::GroupCalcEnabled;
+    return true;
 }
 
 bool ScFormulaCell::InterpretInvariantFormulaGroup()
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index 79621ea..b20b437 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -33,18 +33,14 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
 {
     // Decompose the group into individual cells and calculate them individually.
 
-    // Always set the top row to be the top of the group.  Grouped formula
-    // cells are to be calculated for its full segment at all times.
-
-    ScAddress aTopPos = rTopPos;
-    aTopPos.SetRow(xGroup->mnStart);
-    ScAddress aTmpPos = aTopPos;
+    // The caller must ensure that the top position is the start position of
+    // the group.
 
+    ScAddress aTmpPos = rTopPos;
     std::vector<double> aResults;
     aResults.reserve(xGroup->mnLength);
-    for (SCROW i = 0; i < xGroup->mnLength; ++i)
+    for (SCROW i = 0; i < xGroup->mnLength; ++i, aTmpPos.IncRow())
     {
-        aTmpPos.SetRow(aTopPos.Row() + i);
         ScTokenArray aCode2;
         for (const formula::FormulaToken* p = rCode.First(); p; p = rCode.Next())
         {
@@ -103,7 +99,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
     } // for loop end (xGroup->mnLength)
 
     if (!aResults.empty())
-        rDoc.SetFormulaResults(aTopPos, &aResults[0], aResults.size());
+        rDoc.SetFormulaResults(rTopPos, &aResults[0], aResults.size());
 
     return true;
 }
commit 041e7dce8097fe2a4fe1cc853cab463dd5ea72e5
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 2 18:55:29 2013 -0400

    Actually we need to reset the top row to be the top of the group.
    
    To ensure that a group of formula cells are either all clean or all
    dirty at any given time. We'll fallback to non-grouped calculation
    mode if that's not possible.
    
    Change-Id: I8a5d4740571ca149d32a4630555e3c213c222ef3

diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index 3dd43e3..79621ea 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -33,14 +33,18 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
 {
     // Decompose the group into individual cells and calculate them individually.
 
-    ScAddress aTmpPos = rTopPos;
-    SCROW nOffset = rTopPos.Row() - xGroup->mnStart;
-    SCROW nLength = xGroup->mnLength - nOffset;
+    // Always set the top row to be the top of the group.  Grouped formula
+    // cells are to be calculated for its full segment at all times.
+
+    ScAddress aTopPos = rTopPos;
+    aTopPos.SetRow(xGroup->mnStart);
+    ScAddress aTmpPos = aTopPos;
+
     std::vector<double> aResults;
-    aResults.reserve(nLength);
-    for (SCROW i = 0; i < nLength; ++i)
+    aResults.reserve(xGroup->mnLength);
+    for (SCROW i = 0; i < xGroup->mnLength; ++i)
     {
-        aTmpPos.SetRow(rTopPos.Row() + i);
+        aTmpPos.SetRow(aTopPos.Row() + i);
         ScTokenArray aCode2;
         for (const formula::FormulaToken* p = rCode.First(); p; p = rCode.Next())
         {
@@ -99,7 +103,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
     } // for loop end (xGroup->mnLength)
 
     if (!aResults.empty())
-        rDoc.SetFormulaResults(rTopPos, &aResults[0], aResults.size());
+        rDoc.SetFormulaResults(aTopPos, &aResults[0], aResults.size());
 
     return true;
 }
commit 75cfc9a332b224597872960df22091ca76747058
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 2 16:47:31 2013 -0400

    Be aware that the top row may not always be the top of the group.
    
    Adjust the length and the starting row position for accordingly.
    
    Change-Id: I2f9c5a515887b98334bad51c5409461d5dd1505d

diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index 4754bd0..3dd43e3 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -18,6 +18,8 @@
 
 #include "formula/vectortoken.hxx"
 
+#include <vector>
+
 namespace sc {
 
 ScMatrixRef FormulaGroupInterpreterSoftware::inverseMatrix(const ScMatrix& /*rMat*/)
@@ -29,12 +31,16 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
                                                 const ScFormulaCellGroupRef& xGroup,
                                                 ScTokenArray& rCode)
 {
-    // Until we implement group calculation for real, decompose the group into
-    // individual formula token arrays for individual calculation.
+    // Decompose the group into individual cells and calculate them individually.
+
     ScAddress aTmpPos = rTopPos;
-    for (sal_Int32 i = 0; i < xGroup->mnLength; ++i)
+    SCROW nOffset = rTopPos.Row() - xGroup->mnStart;
+    SCROW nLength = xGroup->mnLength - nOffset;
+    std::vector<double> aResults;
+    aResults.reserve(nLength);
+    for (SCROW i = 0; i < nLength; ++i)
     {
-        aTmpPos.SetRow(xGroup->mnStart + i);
+        aTmpPos.SetRow(rTopPos.Row() + i);
         ScTokenArray aCode2;
         for (const formula::FormulaToken* p = rCode.First(); p; p = rCode.Next())
         {
@@ -89,11 +95,12 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
         aComp.CompileTokenArray(); // Create RPN token array.
         ScInterpreter aInterpreter(pDest, &rDoc, aTmpPos, aCode2);
         aInterpreter.Interpret();
-        pDest->SetResultToken(aInterpreter.GetResultToken().get());
-        pDest->ResetDirty();
-        pDest->SetChanged(true);
+        aResults.push_back(aInterpreter.GetResultToken()->GetDouble());
     } // for loop end (xGroup->mnLength)
 
+    if (!aResults.empty())
+        rDoc.SetFormulaResults(rTopPos, &aResults[0], aResults.size());
+
     return true;
 }
 
commit d61233a388284383a939e2f26a0e25b9ad243898
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 2 16:02:59 2013 -0400

    Move this code from the column code back into the interpreter code.
    
    Change-Id: I7830cdf3f09ed7b6ae6221212bfb84abcdeac523

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 359b8ac..62e1ddf 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -409,9 +409,6 @@ public:
     void        ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark );
     void        ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark );
 
-    double SumNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const;
-    size_t CountNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const;
-
     long GetNeededSize(
         SCROW nRow, OutputDevice* pDev, double nPPTX, double nPPTY,
         const Fraction& rZoomX, const Fraction& rZoomY,
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 61f57ab..6a2dbd3 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -466,80 +466,6 @@ void ScColumn::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
     }
 }
 
-namespace {
-
-class NumericCellAccumulator
-{
-    double mfSum;
-public:
-    NumericCellAccumulator() : mfSum(0.0) {}
-
-    void operator() (size_t, double fVal)
-    {
-        mfSum += fVal;
-    }
-
-    void operator() (size_t, const ScFormulaCell* pCell)
-    {
-        ScFormulaCell& rCell = const_cast<ScFormulaCell&>(*pCell);
-        if (rCell.IsValue())
-            mfSum += rCell.GetValue();
-    }
-
-    double getSum() const { return mfSum; }
-};
-
-class NumericCellCounter
-{
-    size_t mnCount;
-public:
-    NumericCellCounter() : mnCount(0) {}
-
-    void operator() (const sc::CellStoreType::value_type& rNode, size_t nOffset, size_t nDataSize)
-    {
-        switch (rNode.type)
-        {
-            case sc::element_type_numeric:
-                mnCount += nDataSize;
-            break;
-            case sc::element_type_formula:
-            {
-                sc::formula_block::const_iterator it = sc::formula_block::begin(*rNode.data);
-                std::advance(it, nOffset);
-                sc::formula_block::const_iterator itEnd = it;
-                std::advance(itEnd, nDataSize);
-                for (; it != itEnd; ++it)
-                {
-                    ScFormulaCell& rCell = const_cast<ScFormulaCell&>(**it);
-                    if (rCell.IsValueNoError())
-                        ++mnCount;
-                }
-            }
-            break;
-            default:
-                ;
-        }
-    }
-
-    size_t getCount() const { return mnCount; }
-};
-
-}
-
-double ScColumn::SumNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const
-{
-    NumericCellAccumulator aFunc;
-    rPos.miCellPos = sc::ParseFormulaNumeric(rPos.miCellPos, maCells, nRow1, nRow2, aFunc);
-    return aFunc.getSum();
-}
-
-size_t ScColumn::CountNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const
-{
-    NumericCellCounter aFunc;
-    rPos.miCellPos = sc::ParseBlock(rPos.miCellPos, maCells, aFunc, nRow1, nRow2);
-    return aFunc.getCount();
-}
-
 void ScColumn::ClearSelectionItems( const sal_uInt16* pWhich,const ScMarkData& rMark )
 {
     SCROW nTop;
diff --git a/sc/source/core/tool/interpr6.cxx b/sc/source/core/tool/interpr6.cxx
index e31a062..03d87a9 100644
--- a/sc/source/core/tool/interpr6.cxx
+++ b/sc/source/core/tool/interpr6.cxx
@@ -24,6 +24,7 @@
 #include "document.hxx"
 #include "cellvalue.hxx"
 #include "dociter.hxx"
+#include "mtvcellfunc.hxx"
 
 #include "formula/token.hxx"
 #include <rtl/logfile.hxx>
@@ -213,6 +214,62 @@ double ScInterpreter::GetGammaDist( double fX, double fAlpha, double fLambda )
 
 namespace {
 
+class NumericCellAccumulator
+{
+    double mfSum;
+public:
+    NumericCellAccumulator() : mfSum(0.0) {}
+
+    void operator() (size_t, double fVal)
+    {
+        mfSum += fVal;
+    }
+
+    void operator() (size_t, const ScFormulaCell* pCell)
+    {
+        ScFormulaCell& rCell = const_cast<ScFormulaCell&>(*pCell);
+        if (rCell.IsValue())
+            mfSum += rCell.GetValue();
+    }
+
+    double getSum() const { return mfSum; }
+};
+
+class NumericCellCounter
+{
+    size_t mnCount;
+public:
+    NumericCellCounter() : mnCount(0) {}
+
+    void operator() (const sc::CellStoreType::value_type& rNode, size_t nOffset, size_t nDataSize)
+    {
+        switch (rNode.type)
+        {
+            case sc::element_type_numeric:
+                mnCount += nDataSize;
+            break;
+            case sc::element_type_formula:
+            {
+                sc::formula_block::const_iterator it = sc::formula_block::begin(*rNode.data);
+                std::advance(it, nOffset);
+                sc::formula_block::const_iterator itEnd = it;
+                std::advance(itEnd, nDataSize);
+                for (; it != itEnd; ++it)
+                {
+                    ScFormulaCell& rCell = const_cast<ScFormulaCell&>(**it);
+                    if (rCell.IsValueNoError())
+                        ++mnCount;
+                }
+            }
+            break;
+            default:
+                ;
+        }
+    }
+
+    size_t getCount() const { return mnCount; }
+};
+
 class FuncCount : public sc::ColumnSpanSet::ColumnAction
 {
     sc::ColumnBlockConstPosition maPos;
@@ -234,7 +291,9 @@ public:
         if (!bVal)
             return;
 
-        mnCount += mpCol->CountNumericCells(maPos, nRow1, nRow2);
+        NumericCellCounter aFunc;
+        maPos.miCellPos = sc::ParseBlock(maPos.miCellPos, mpCol->GetCellStore(), aFunc, nRow1, nRow2);
+        mnCount += aFunc.getCount();
         mnNumFmt = mpCol->GetNumberFormat(nRow2);
     };
 
@@ -263,7 +322,9 @@ public:
         if (!bVal)
             return;
 
-        mfSum += mpCol->SumNumericCells(maPos, nRow1, nRow2);
+        NumericCellAccumulator aFunc;
+        maPos.miCellPos = sc::ParseFormulaNumeric(maPos.miCellPos, mpCol->GetCellStore(), nRow1, nRow2, aFunc);
+        mfSum += aFunc.getSum();
         mnNumFmt = mpCol->GetNumberFormat(nRow2);
     };
 
commit 4277d968eb4407e22a3d4b467340a347e43e7ea9
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Jul 2 15:43:57 2013 -0400

    Move this to another file to distribute the compiler load.
    
    interpr1.cxx is getting way too big....
    
    Change-Id: Ic3e4879daebd09c8dcb86a42b305864dcc1c67c4

diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 93bcfef..8b738fa 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -58,8 +58,6 @@
 #include "queryparam.hxx"
 #include "queryentry.hxx"
 #include "tokenarray.hxx"
-#include "columnspanset.hxx"
-#include "column.hxx"
 
 #include <comphelper/processfactory.hxx>
 #include <comphelper/string.hxx>
@@ -3852,771 +3850,6 @@ void ScInterpreter::ScMax( bool bTextAsZero )
         PushDouble(nMax);
 }
 
-namespace {
-
-class FuncCount : public sc::ColumnSpanSet::ColumnAction
-{
-    sc::ColumnBlockConstPosition maPos;
-    ScColumn* mpCol;
-    size_t mnCount;
-    sal_uInt32 mnNumFmt;
-
-public:
-    FuncCount() : mnCount(0), mnNumFmt(0) {}
-
-    virtual void startColumn(ScColumn* pCol)
-    {
-        mpCol = pCol;
-        mpCol->InitBlockPosition(maPos);
-    }
-
-    virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
-    {
-        if (!bVal)
-            return;
-
-        mnCount += mpCol->CountNumericCells(maPos, nRow1, nRow2);
-        mnNumFmt = mpCol->GetNumberFormat(nRow2);
-    };
-
-    size_t getCount() const { return mnCount; }
-    sal_uInt32 getNumberFormat() const { return mnNumFmt; }
-};
-
-class FuncSum : public sc::ColumnSpanSet::ColumnAction
-{
-    sc::ColumnBlockConstPosition maPos;
-    ScColumn* mpCol;
-    double mfSum;
-    sal_uInt32 mnNumFmt;
-
-public:
-    FuncSum() : mfSum(0.0), mnNumFmt(0) {}
-
-    virtual void startColumn(ScColumn* pCol)
-    {
-        mpCol = pCol;
-        mpCol->InitBlockPosition(maPos);
-    }
-
-    virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
-    {
-        if (!bVal)
-            return;
-
-        mfSum += mpCol->SumNumericCells(maPos, nRow1, nRow2);
-        mnNumFmt = mpCol->GetNumberFormat(nRow2);
-    };
-
-    double getSum() const { return mfSum; }
-    sal_uInt32 getNumberFormat() const { return mnNumFmt; }
-};
-
-void IterateMatrix(
-    const ScMatrixRef& pMat, ScIterFunc eFunc, bool bTextAsZero,
-    sal_uLong& rCount, short& rFuncFmtType, double& fRes, double& fMem, bool& bNull)
-{
-    if (!pMat)
-        return;
-
-    rFuncFmtType = NUMBERFORMAT_NUMBER;
-    switch (eFunc)
-    {
-        case ifAVERAGE:
-        case ifSUM:
-        {
-            ScMatrix::IterateResult aRes = pMat->Sum(bTextAsZero);
-            if (bNull)
-            {
-                bNull = false;
-                fMem = aRes.mfFirst;
-                fRes += aRes.mfRest;
-            }
-            else
-                fRes += aRes.mfFirst + aRes.mfRest;
-            rCount += aRes.mnCount;
-        }
-        break;
-        case ifCOUNT:
-            rCount += pMat->Count(bTextAsZero);
-        break;
-        case ifCOUNT2:
-            rCount += pMat->Count(true);
-        break;
-        case ifPRODUCT:
-        {
-            ScMatrix::IterateResult aRes = pMat->Product(bTextAsZero);
-            fRes *= aRes.mfRest;
-            rCount += aRes.mnCount;
-        }
-        break;
-        case ifSUMSQ:
-        {
-            ScMatrix::IterateResult aRes = pMat->SumSquare(bTextAsZero);
-            fRes += aRes.mfRest;
-            rCount += aRes.mnCount;
-        }
-        break;
-        default:
-            ;
-    }
-}
-
-}
-
-double ScInterpreter::IterateParameters( ScIterFunc eFunc, bool bTextAsZero )
-{
-    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IterateParameters" );
-    short nParamCount = GetByte();
-    double fRes = ( eFunc == ifPRODUCT ) ? 1.0 : 0.0;
-    double fVal = 0.0;
-    double fMem = 0.0; // first numeric value.
-    bool bNull = true;
-    sal_uLong nCount = 0;
-    ScAddress aAdr;
-    ScRange aRange;
-    size_t nRefInList = 0;
-    if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
-        nGlobalError = 0;
-    while (nParamCount-- > 0)
-    {
-        switch (GetStackType())
-        {
-            case svString:
-            {
-                if( eFunc == ifCOUNT )
-                {
-                    String aStr( PopString() );
-                    sal_uInt32 nFIndex = 0;                 // damit default Land/Spr.
-                    if ( bTextAsZero || pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
-                        nCount++;
-                }
-                else
-                {
-                    switch ( eFunc )
-                    {
-                        case ifAVERAGE:
-                        case ifSUM:
-                        case ifSUMSQ:
-                        case ifPRODUCT:
-                        {
-                            if ( bTextAsZero )
-                            {
-                                Pop();
-                                nCount++;
-                                if ( eFunc == ifPRODUCT )
-                                    fRes = 0.0;
-                            }
-                            else
-                            {
-                                while (nParamCount-- > 0)
-                                    Pop();
-                                SetError( errNoValue );
-                            }
-                        }
-                        break;
-                        default:
-                            Pop();
-                            nCount++;
-                    }
-                }
-            }
-            break;
-            case svDouble    :
-                fVal = GetDouble();
-                nCount++;
-                switch( eFunc )
-                {
-                    case ifAVERAGE:
-                    case ifSUM:
-                        if ( bNull && fVal != 0.0 )
-                        {
-                            bNull = false;
-                            fMem = fVal;
-                        }
-                        else
-                            fRes += fVal;
-                        break;
-                    case ifSUMSQ:   fRes += fVal * fVal; break;
-                    case ifPRODUCT: fRes *= fVal; break;
-                    default: ; // nothing
-                }
-                nFuncFmtType = NUMBERFORMAT_NUMBER;
-                break;
-            case svExternalSingleRef:
-            {
-                ScExternalRefCache::TokenRef pToken;
-                ScExternalRefCache::CellFormat aFmt;
-                PopExternalSingleRef(pToken, &aFmt);
-                if (nGlobalError && (eFunc == ifCOUNT2 || eFunc == ifCOUNT))
-                {
-                    nGlobalError = 0;
-                    if ( eFunc == ifCOUNT2 )
-                        ++nCount;
-                    break;
-                }
-
-                if (!pToken)
-                    break;
-
-                StackVar eType = pToken->GetType();
-                if (eFunc == ifCOUNT2)
-                {
-                    if (eType != formula::svEmptyCell)
-                        nCount++;
-                    if (nGlobalError)
-                        nGlobalError = 0;
-                }
-                else if (eType == formula::svDouble)
-                {
-                    nCount++;
-                    fVal = pToken->GetDouble();
-                    if (aFmt.mbIsSet)
-                    {
-                        nFuncFmtType = aFmt.mnType;
-                        nFuncFmtIndex = aFmt.mnIndex;
-                    }
-                    switch( eFunc )
-                    {
-                        case ifAVERAGE:
-                        case ifSUM:
-                            if ( bNull && fVal != 0.0 )
-                            {
-                                bNull = false;
-                                fMem = fVal;
-                            }
-                            else
-                                fRes += fVal;
-                            break;
-                        case ifSUMSQ:   fRes += fVal * fVal; break;
-                        case ifPRODUCT: fRes *= fVal; break;
-                        case ifCOUNT:
-                            if ( nGlobalError )
-                            {
-                                nGlobalError = 0;
-                                nCount--;
-                            }
-                            break;
-                        default: ; // nothing
-                    }
-                }
-                else if (bTextAsZero && eType == formula::svString)
-                {
-                    nCount++;
-                    if ( eFunc == ifPRODUCT )
-                        fRes = 0.0;
-                }
-            }
-            break;
-            case svSingleRef :
-            {
-                PopSingleRef( aAdr );
-                if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
-                {
-                    nGlobalError = 0;
-                    if ( eFunc == ifCOUNT2 )
-                        ++nCount;
-                    break;
-                }
-                if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
-                {
-                    break;
-                }
-                ScRefCellValue aCell;
-                aCell.assign(*pDok, aAdr);
-                if (!aCell.isEmpty())
-                {
-                    if( eFunc == ifCOUNT2 )
-                    {
-                        CellType eCellType = aCell.meType;
-                        if (eCellType != CELLTYPE_NONE)
-                            nCount++;
-                        if ( nGlobalError )
-                            nGlobalError = 0;
-                    }
-                    else if (aCell.hasNumeric())
-                    {
-                        nCount++;
-                        fVal = GetCellValue(aAdr, aCell);
-                        CurFmtToFuncFmt();
-                        switch( eFunc )
-                        {
-                            case ifAVERAGE:
-                            case ifSUM:
-                                if ( bNull && fVal != 0.0 )
-                                {
-                                    bNull = false;
-                                    fMem = fVal;
-                                }
-                                else
-                                    fRes += fVal;
-                                break;
-                            case ifSUMSQ:   fRes += fVal * fVal; break;
-                            case ifPRODUCT: fRes *= fVal; break;
-                            case ifCOUNT:
-                                if ( nGlobalError )
-                                {
-                                    nGlobalError = 0;
-                                    nCount--;
-                                }
-                                break;
-                            default: ; // nothing
-                        }
-                    }
-                    else if (bTextAsZero && aCell.hasString())
-                    {
-                        nCount++;
-                        if ( eFunc == ifPRODUCT )
-                            fRes = 0.0;
-                    }
-                }
-            }
-            break;
-            case svDoubleRef :
-            case svRefList :
-            {
-                PopDoubleRef( aRange, nParamCount, nRefInList);
-                if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
-                {
-                    nGlobalError = 0;
-                    if ( eFunc == ifCOUNT2 )
-                        ++nCount;
-                    break;
-                }
-                if( eFunc == ifCOUNT2 )
-                {
-                    ScCellIterator aIter( pDok, aRange, glSubTotal );
-                    for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
-                    {
-                        if (!aIter.hasEmptyData())
-                            ++nCount;
-                    }
-
-                    if ( nGlobalError )
-                        nGlobalError = 0;
-                }
-                else
-                {
-                    ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
-                    sal_uInt16 nErr = 0;
-                    if (aValIter.GetFirst(fVal, nErr))
-                    {
-                        // placed the loop on the inside for performance reasons:
-                        aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
-                        switch( eFunc )
-                        {
-                            case ifAVERAGE:
-                            case ifSUM:
-                                    do
-                                    {
-                                        SetError(nErr);
-                                        if ( bNull && fVal != 0.0 )
-                                        {
-                                            bNull = false;
-                                            fMem = fVal;
-                                        }
-                                        else
-                                            fRes += fVal;
-                                        nCount++;
-                                    }
-                                    while (aValIter.GetNext(fVal, nErr));
-                                    break;
-                            case ifSUMSQ:
-                                    do
-                                    {
-                                        SetError(nErr);
-                                        fRes += fVal * fVal;
-                                        nCount++;
-                                    }
-                                    while (aValIter.GetNext(fVal, nErr));
-                                    break;
-                            case ifPRODUCT:
-                                    do
-                                    {
-                                        SetError(nErr);
-                                        fRes *= fVal;
-                                        nCount++;
-                                    }
-                                    while (aValIter.GetNext(fVal, nErr));
-                                    break;
-                            case ifCOUNT:
-                                    do
-                                    {
-                                        if ( !nErr )
-                                            nCount++;
-                                    }
-                                    while (aValIter.GetNext(fVal, nErr));
-                                    break;
-                            default: ;  // nothing
-                        }
-                        SetError( nErr );
-                    }
-                }
-            }
-            break;
-            case svExternalDoubleRef:
-            {
-                ScMatrixRef pMat;
-                PopExternalDoubleRef(pMat);
-                if (nGlobalError)
-                    break;
-
-                IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
-            }
-            break;
-            case svMatrix :
-            {
-                ScMatrixRef pMat = PopMatrix();
-                IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
-            }
-            break;
-            case svError:
-            {
-                PopError();
-                if ( eFunc == ifCOUNT )
-                {
-                    nGlobalError = 0;
-                }
-                else if ( eFunc == ifCOUNT2 )
-                {
-                    nCount++;
-                    nGlobalError = 0;
-                }
-            }
-            break;
-            default :
-                while (nParamCount-- > 0)
-                    PopError();
-                SetError(errIllegalParameter);
-        }
-    }
-    switch( eFunc )
-    {
-        case ifSUM:     fRes = ::rtl::math::approxAdd( fRes, fMem ); break;
-        case ifAVERAGE: fRes = div(::rtl::math::approxAdd( fRes, fMem ), nCount); break;
-        case ifCOUNT2:
-        case ifCOUNT:   fRes  = nCount; break;
-        case ifPRODUCT: if ( !nCount ) fRes = 0.0; break;
-        default: ; // nothing
-    }
-    // Bei Summen etc. macht ein bool-Ergebnis keinen Sinn
-    // und Anzahl ist immer Number (#38345#)
-    if( eFunc == ifCOUNT || nFuncFmtType == NUMBERFORMAT_LOGICAL )
-        nFuncFmtType = NUMBERFORMAT_NUMBER;
-    return fRes;
-}
-
-
-void ScInterpreter::ScSumSQ()
-{
-    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSumSQ" );
-    PushDouble( IterateParameters( ifSUMSQ ) );
-}
-
-
-void ScInterpreter::ScSum()
-{
-    short nParamCount = GetByte();
-    double fRes = 0.0;
-    double fVal = 0.0;
-    ScAddress aAdr;
-    ScRange aRange;
-    size_t nRefInList = 0;
-    while (nParamCount-- > 0)
-    {
-        switch (GetStackType())
-        {
-            case svString:
-            {
-                while (nParamCount-- > 0)
-                    Pop();
-                SetError( errNoValue );
-            }
-            break;
-            case svDouble    :
-                fVal = GetDouble();
-                fRes += fVal;
-                nFuncFmtType = NUMBERFORMAT_NUMBER;
-                break;
-            case svExternalSingleRef:
-            {
-                ScExternalRefCache::TokenRef pToken;
-                ScExternalRefCache::CellFormat aFmt;
-                PopExternalSingleRef(pToken, &aFmt);
-
-                if (!pToken)
-                    break;
-
-                StackVar eType = pToken->GetType();
-                if (eType == formula::svDouble)
-                {
-                    fVal = pToken->GetDouble();
-                    if (aFmt.mbIsSet)
-                    {
-                        nFuncFmtType = aFmt.mnType;
-                        nFuncFmtIndex = aFmt.mnIndex;
-                    }
-
-                    fRes += fVal;
-                }
-            }
-            break;
-            case svSingleRef :
-            {
-                PopSingleRef( aAdr );
-
-                if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
-                {
-                    break;
-                }
-                ScRefCellValue aCell;
-                aCell.assign(*pDok, aAdr);
-                if (!aCell.isEmpty())
-                {
-                    if (aCell.hasNumeric())
-                    {
-                        fVal = GetCellValue(aAdr, aCell);
-                        CurFmtToFuncFmt();
-                        fRes += fVal;
-                    }
-                }
-            }
-            break;
-            case svDoubleRef :
-            case svRefList :
-            {
-                PopDoubleRef( aRange, nParamCount, nRefInList);
-
-                sc::ColumnSpanSet aSet(false);
-                aSet.set(aRange, true);
-                if (glSubTotal)
-                    // Skip all filtered rows and subtotal formula cells.
-                    pDok->MarkSubTotalCells(aSet, aRange, false);
-
-                FuncSum aAction;
-                aSet.executeColumnAction(*pDok, aAction);
-                fRes = aAction.getSum();
-
-                // Get the number format of the last iterated cell.
-                nFuncFmtIndex = aAction.getNumberFormat();
-                nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
-            }
-            break;
-            case svExternalDoubleRef:
-            {
-                ScMatrixRef pMat;
-                PopExternalDoubleRef(pMat);
-                if (nGlobalError)
-                    break;
-
-                sal_uLong nCount = 0;
-                double fMem = 0.0;
-                bool bNull = true;
-                IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
-                fRes += fMem;
-            }
-            break;
-            case svMatrix :
-            {
-                ScMatrixRef pMat = PopMatrix();
-                sal_uLong nCount = 0;
-                double fMem = 0.0;
-                bool bNull = true;
-                IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
-                fRes += fMem;
-            }
-            break;
-            case svError:
-            {
-                PopError();
-            }
-            break;
-            default :
-                while (nParamCount-- > 0)
-                    PopError();
-                SetError(errIllegalParameter);
-        }
-    }
-
-    if (nFuncFmtType == NUMBERFORMAT_LOGICAL)
-        nFuncFmtType = NUMBERFORMAT_NUMBER;
-
-    PushDouble(fRes);
-}
-
-
-void ScInterpreter::ScProduct()
-{
-    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScProduct" );
-    PushDouble( IterateParameters( ifPRODUCT ) );
-}
-
-
-void ScInterpreter::ScAverage( bool bTextAsZero )
-{
-    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAverage" );
-    PushDouble( IterateParameters( ifAVERAGE, bTextAsZero ) );
-}
-
-void ScInterpreter::ScCount()
-{
-    short nParamCount = GetByte();
-    double fVal = 0.0;
-    sal_uLong nCount = 0;
-    ScAddress aAdr;
-    ScRange aRange;
-    size_t nRefInList = 0;
-    if (nGlobalError)
-        nGlobalError = 0;
-
-    while (nParamCount-- > 0)
-    {
-        switch (GetStackType())
-        {
-            case svString:
-            {
-                String aStr( PopString() );
-                sal_uInt32 nFIndex = 0;                 // damit default Land/Spr.
-                if (pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
-                    nCount++;
-            }
-            break;
-            case svDouble    :
-                nCount++;
-                nFuncFmtType = NUMBERFORMAT_NUMBER;
-                break;
-            case svExternalSingleRef:
-            {
-                ScExternalRefCache::TokenRef pToken;
-                ScExternalRefCache::CellFormat aFmt;
-                PopExternalSingleRef(pToken, &aFmt);
-                if (nGlobalError)
-                {
-                    nGlobalError = 0;
-                    break;
-                }
-
-                if (!pToken)
-                    break;
-
-                StackVar eType = pToken->GetType();
-                if (eType == formula::svDouble)
-                {
-                    nCount++;
-                    if (aFmt.mbIsSet)
-                    {
-                        nFuncFmtType = aFmt.mnType;
-                        nFuncFmtIndex = aFmt.mnIndex;
-                    }
-
-                    if (nGlobalError)
-                    {
-                        nGlobalError = 0;
-                        nCount--;
-                    }
-                }
-            }
-            break;
-            case svSingleRef :
-            {
-                PopSingleRef( aAdr );
-                if (nGlobalError)
-                {
-                    nGlobalError = 0;
-                    break;
-                }
-                if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
-                {
-                    break;
-                }
-                ScRefCellValue aCell;
-                aCell.assign(*pDok, aAdr);
-                if (!aCell.isEmpty())
-                {
-                    if (aCell.hasNumeric())
-                    {
-                        nCount++;
-                        CurFmtToFuncFmt();
-                        if (nGlobalError)
-                        {
-                            nGlobalError = 0;
-                            nCount--;
-                        }
-                    }
-                }
-            }
-            break;
-            case svDoubleRef :
-            case svRefList :
-            {
-                PopDoubleRef( aRange, nParamCount, nRefInList);
-                if (nGlobalError)
-                {
-                    nGlobalError = 0;
-                    break;
-                }
-
-                sc::ColumnSpanSet aSet(false);
-                aSet.set(aRange, true);
-                if (glSubTotal)
-                    // Skip all filtered rows and subtotal formula cells.
-                    pDok->MarkSubTotalCells(aSet, aRange, false);
-
-                FuncCount aAction;
-                aSet.executeColumnAction(*pDok, aAction);
-                nCount = aAction.getCount();
-
-                // Get the number format of the last iterated cell.
-                nFuncFmtIndex = aAction.getNumberFormat();
-                nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
-            }
-            break;
-            case svExternalDoubleRef:
-            {
-                ScMatrixRef pMat;
-                PopExternalDoubleRef(pMat);
-                if (nGlobalError)
-                    break;
-
-                double fMem = 0.0, fRes = 0.0;
-                bool bNull = true;
-                IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
-            }
-            break;
-            case svMatrix :
-            {
-                ScMatrixRef pMat = PopMatrix();
-                double fMem = 0.0, fRes = 0.0;
-                bool bNull = true;
-                IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
-            }
-            break;
-            case svError:
-            {
-                PopError();
-                nGlobalError = 0;
-            }
-            break;
-            default :
-                while (nParamCount-- > 0)
-                    PopError();
-                SetError(errIllegalParameter);
-        }
-    }
-
-    nFuncFmtType = NUMBERFORMAT_NUMBER;
-
-    PushDouble(nCount);
-}
-
-
-void ScInterpreter::ScCount2()
-{
-    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCount2" );
-    PushDouble( IterateParameters( ifCOUNT2 ) );
-}
-
-
 void ScInterpreter::GetStVarParams( double& rVal, double& rValCount,
                 bool bTextAsZero )
 {
diff --git a/sc/source/core/tool/interpr6.cxx b/sc/source/core/tool/interpr6.cxx
index 7f712e3..e31a062 100644
--- a/sc/source/core/tool/interpr6.cxx
+++ b/sc/source/core/tool/interpr6.cxx
@@ -18,8 +18,17 @@
  */
 
 
-#include <rtl/logfile.hxx>
 #include "interpre.hxx"
+#include "columnspanset.hxx"
+#include "column.hxx"
+#include "document.hxx"
+#include "cellvalue.hxx"
+#include "dociter.hxx"
+
+#include "formula/token.hxx"
+#include <rtl/logfile.hxx>
+
+using namespace formula;
 
 double const fHalfMachEps = 0.5 * ::std::numeric_limits<double>::epsilon();
 
@@ -202,4 +211,768 @@ double ScInterpreter::GetGammaDist( double fX, double fAlpha, double fLambda )
         return GetLowRegIGamma( fAlpha, fX / fLambda);
 }
 
+namespace {
+
+class FuncCount : public sc::ColumnSpanSet::ColumnAction
+{
+    sc::ColumnBlockConstPosition maPos;
+    ScColumn* mpCol;
+    size_t mnCount;
+    sal_uInt32 mnNumFmt;
+
+public:
+    FuncCount() : mnCount(0), mnNumFmt(0) {}
+
+    virtual void startColumn(ScColumn* pCol)
+    {
+        mpCol = pCol;
+        mpCol->InitBlockPosition(maPos);
+    }
+
+    virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
+    {
+        if (!bVal)
+            return;
+
+        mnCount += mpCol->CountNumericCells(maPos, nRow1, nRow2);
+        mnNumFmt = mpCol->GetNumberFormat(nRow2);
+    };
+
+    size_t getCount() const { return mnCount; }
+    sal_uInt32 getNumberFormat() const { return mnNumFmt; }
+};
+
+class FuncSum : public sc::ColumnSpanSet::ColumnAction
+{
+    sc::ColumnBlockConstPosition maPos;
+    ScColumn* mpCol;
+    double mfSum;
+    sal_uInt32 mnNumFmt;
+
+public:
+    FuncSum() : mfSum(0.0), mnNumFmt(0) {}
+
+    virtual void startColumn(ScColumn* pCol)
+    {
+        mpCol = pCol;
+        mpCol->InitBlockPosition(maPos);
+    }
+
+    virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
+    {
+        if (!bVal)
+            return;
+
+        mfSum += mpCol->SumNumericCells(maPos, nRow1, nRow2);
+        mnNumFmt = mpCol->GetNumberFormat(nRow2);
+    };
+
+    double getSum() const { return mfSum; }
+    sal_uInt32 getNumberFormat() const { return mnNumFmt; }
+};
+
+void IterateMatrix(
+    const ScMatrixRef& pMat, ScIterFunc eFunc, bool bTextAsZero,
+    sal_uLong& rCount, short& rFuncFmtType, double& fRes, double& fMem, bool& bNull)
+{
+    if (!pMat)
+        return;
+
+    rFuncFmtType = NUMBERFORMAT_NUMBER;
+    switch (eFunc)
+    {
+        case ifAVERAGE:
+        case ifSUM:
+        {
+            ScMatrix::IterateResult aRes = pMat->Sum(bTextAsZero);
+            if (bNull)
+            {
+                bNull = false;
+                fMem = aRes.mfFirst;
+                fRes += aRes.mfRest;
+            }
+            else
+                fRes += aRes.mfFirst + aRes.mfRest;
+            rCount += aRes.mnCount;
+        }
+        break;
+        case ifCOUNT:
+            rCount += pMat->Count(bTextAsZero);
+        break;
+        case ifCOUNT2:
+            rCount += pMat->Count(true);
+        break;
+        case ifPRODUCT:
+        {
+            ScMatrix::IterateResult aRes = pMat->Product(bTextAsZero);
+            fRes *= aRes.mfRest;
+            rCount += aRes.mnCount;
+        }
+        break;
+        case ifSUMSQ:
+        {
+            ScMatrix::IterateResult aRes = pMat->SumSquare(bTextAsZero);
+            fRes += aRes.mfRest;
+            rCount += aRes.mnCount;
+        }
+        break;
+        default:
+            ;
+    }
+}
+
+}
+
+double ScInterpreter::IterateParameters( ScIterFunc eFunc, bool bTextAsZero )
+{
+    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IterateParameters" );
+    short nParamCount = GetByte();
+    double fRes = ( eFunc == ifPRODUCT ) ? 1.0 : 0.0;
+    double fVal = 0.0;
+    double fMem = 0.0; // first numeric value.
+    bool bNull = true;
+    sal_uLong nCount = 0;
+    ScAddress aAdr;
+    ScRange aRange;
+    size_t nRefInList = 0;
+    if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
+        nGlobalError = 0;
+    while (nParamCount-- > 0)
+    {
+        switch (GetStackType())
+        {
+            case svString:
+            {
+                if( eFunc == ifCOUNT )
+                {
+                    String aStr( PopString() );
+                    sal_uInt32 nFIndex = 0;                 // damit default Land/Spr.
+                    if ( bTextAsZero || pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
+                        nCount++;
+                }
+                else
+                {
+                    switch ( eFunc )
+                    {
+                        case ifAVERAGE:
+                        case ifSUM:
+                        case ifSUMSQ:
+                        case ifPRODUCT:
+                        {
+                            if ( bTextAsZero )
+                            {
+                                Pop();
+                                nCount++;
+                                if ( eFunc == ifPRODUCT )
+                                    fRes = 0.0;
+                            }
+                            else
+                            {
+                                while (nParamCount-- > 0)
+                                    Pop();
+                                SetError( errNoValue );
+                            }
+                        }
+                        break;
+                        default:
+                            Pop();
+                            nCount++;
+                    }
+                }
+            }
+            break;
+            case svDouble    :
+                fVal = GetDouble();
+                nCount++;
+                switch( eFunc )
+                {
+                    case ifAVERAGE:
+                    case ifSUM:
+                        if ( bNull && fVal != 0.0 )
+                        {
+                            bNull = false;
+                            fMem = fVal;
+                        }
+                        else
+                            fRes += fVal;
+                        break;
+                    case ifSUMSQ:   fRes += fVal * fVal; break;
+                    case ifPRODUCT: fRes *= fVal; break;
+                    default: ; // nothing
+                }
+                nFuncFmtType = NUMBERFORMAT_NUMBER;
+                break;
+            case svExternalSingleRef:
+            {
+                ScExternalRefCache::TokenRef pToken;
+                ScExternalRefCache::CellFormat aFmt;
+                PopExternalSingleRef(pToken, &aFmt);
+                if (nGlobalError && (eFunc == ifCOUNT2 || eFunc == ifCOUNT))
+                {
+                    nGlobalError = 0;
+                    if ( eFunc == ifCOUNT2 )
+                        ++nCount;
+                    break;
+                }
+
+                if (!pToken)
+                    break;
+
+                StackVar eType = pToken->GetType();
+                if (eFunc == ifCOUNT2)
+                {
+                    if (eType != formula::svEmptyCell)
+                        nCount++;
+                    if (nGlobalError)
+                        nGlobalError = 0;
+                }
+                else if (eType == formula::svDouble)
+                {
+                    nCount++;
+                    fVal = pToken->GetDouble();
+                    if (aFmt.mbIsSet)
+                    {
+                        nFuncFmtType = aFmt.mnType;
+                        nFuncFmtIndex = aFmt.mnIndex;
+                    }
+                    switch( eFunc )
+                    {
+                        case ifAVERAGE:
+                        case ifSUM:
+                            if ( bNull && fVal != 0.0 )
+                            {
+                                bNull = false;
+                                fMem = fVal;
+                            }
+                            else
+                                fRes += fVal;
+                            break;
+                        case ifSUMSQ:   fRes += fVal * fVal; break;
+                        case ifPRODUCT: fRes *= fVal; break;
+                        case ifCOUNT:
+                            if ( nGlobalError )
+                            {
+                                nGlobalError = 0;
+                                nCount--;
+                            }
+                            break;
+                        default: ; // nothing
+                    }
+                }
+                else if (bTextAsZero && eType == formula::svString)
+                {
+                    nCount++;
+                    if ( eFunc == ifPRODUCT )
+                        fRes = 0.0;
+                }
+            }
+            break;
+            case svSingleRef :
+            {
+                PopSingleRef( aAdr );
+                if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
+                {
+                    nGlobalError = 0;
+                    if ( eFunc == ifCOUNT2 )
+                        ++nCount;
+                    break;
+                }
+                if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
+                {
+                    break;
+                }
+                ScRefCellValue aCell;
+                aCell.assign(*pDok, aAdr);
+                if (!aCell.isEmpty())
+                {
+                    if( eFunc == ifCOUNT2 )
+                    {
+                        CellType eCellType = aCell.meType;
+                        if (eCellType != CELLTYPE_NONE)
+                            nCount++;
+                        if ( nGlobalError )
+                            nGlobalError = 0;
+                    }
+                    else if (aCell.hasNumeric())
+                    {
+                        nCount++;
+                        fVal = GetCellValue(aAdr, aCell);
+                        CurFmtToFuncFmt();
+                        switch( eFunc )
+                        {
+                            case ifAVERAGE:
+                            case ifSUM:
+                                if ( bNull && fVal != 0.0 )
+                                {
+                                    bNull = false;
+                                    fMem = fVal;
+                                }
+                                else
+                                    fRes += fVal;
+                                break;
+                            case ifSUMSQ:   fRes += fVal * fVal; break;
+                            case ifPRODUCT: fRes *= fVal; break;
+                            case ifCOUNT:
+                                if ( nGlobalError )
+                                {
+                                    nGlobalError = 0;
+                                    nCount--;
+                                }
+                                break;
+                            default: ; // nothing
+                        }
+                    }
+                    else if (bTextAsZero && aCell.hasString())
+                    {
+                        nCount++;
+                        if ( eFunc == ifPRODUCT )
+                            fRes = 0.0;
+                    }
+                }
+            }
+            break;
+            case svDoubleRef :
+            case svRefList :
+            {
+                PopDoubleRef( aRange, nParamCount, nRefInList);
+                if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
+                {
+                    nGlobalError = 0;
+                    if ( eFunc == ifCOUNT2 )
+                        ++nCount;
+                    break;
+                }
+                if( eFunc == ifCOUNT2 )
+                {
+                    ScCellIterator aIter( pDok, aRange, glSubTotal );
+                    for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
+                    {
+                        if (!aIter.hasEmptyData())
+                            ++nCount;
+                    }
+
+                    if ( nGlobalError )
+                        nGlobalError = 0;
+                }
+                else
+                {
+                    ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
+                    sal_uInt16 nErr = 0;
+                    if (aValIter.GetFirst(fVal, nErr))
+                    {
+                        // placed the loop on the inside for performance reasons:
+                        aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
+                        switch( eFunc )
+                        {
+                            case ifAVERAGE:
+                            case ifSUM:
+                                    do
+                                    {
+                                        SetError(nErr);
+                                        if ( bNull && fVal != 0.0 )
+                                        {
+                                            bNull = false;
+                                            fMem = fVal;
+                                        }
+                                        else
+                                            fRes += fVal;
+                                        nCount++;
+                                    }
+                                    while (aValIter.GetNext(fVal, nErr));
+                                    break;
+                            case ifSUMSQ:
+                                    do
+                                    {
+                                        SetError(nErr);
+                                        fRes += fVal * fVal;
+                                        nCount++;
+                                    }
+                                    while (aValIter.GetNext(fVal, nErr));
+                                    break;
+                            case ifPRODUCT:
+                                    do
+                                    {
+                                        SetError(nErr);
+                                        fRes *= fVal;
+                                        nCount++;
+                                    }
+                                    while (aValIter.GetNext(fVal, nErr));
+                                    break;
+                            case ifCOUNT:
+                                    do
+                                    {
+                                        if ( !nErr )
+                                            nCount++;
+                                    }
+                                    while (aValIter.GetNext(fVal, nErr));
+                                    break;
+                            default: ;  // nothing
+                        }
+                        SetError( nErr );
+                    }
+                }
+            }
+            break;
+            case svExternalDoubleRef:
+            {
+                ScMatrixRef pMat;
+                PopExternalDoubleRef(pMat);
+                if (nGlobalError)
+                    break;
+
+                IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
+            }
+            break;
+            case svMatrix :
+            {
+                ScMatrixRef pMat = PopMatrix();
+                IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
+            }
+            break;
+            case svError:
+            {
+                PopError();
+                if ( eFunc == ifCOUNT )
+                {
+                    nGlobalError = 0;
+                }
+                else if ( eFunc == ifCOUNT2 )
+                {
+                    nCount++;
+                    nGlobalError = 0;
+                }
+            }
+            break;
+            default :
+                while (nParamCount-- > 0)
+                    PopError();
+                SetError(errIllegalParameter);
+        }
+    }
+    switch( eFunc )
+    {
+        case ifSUM:     fRes = ::rtl::math::approxAdd( fRes, fMem ); break;
+        case ifAVERAGE: fRes = div(::rtl::math::approxAdd( fRes, fMem ), nCount); break;
+        case ifCOUNT2:
+        case ifCOUNT:   fRes  = nCount; break;
+        case ifPRODUCT: if ( !nCount ) fRes = 0.0; break;
+        default: ; // nothing
+    }
+    // Bei Summen etc. macht ein bool-Ergebnis keinen Sinn
+    // und Anzahl ist immer Number (#38345#)
+    if( eFunc == ifCOUNT || nFuncFmtType == NUMBERFORMAT_LOGICAL )
+        nFuncFmtType = NUMBERFORMAT_NUMBER;
+    return fRes;
+}
+
+
+void ScInterpreter::ScSumSQ()
+{
+    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSumSQ" );
+    PushDouble( IterateParameters( ifSUMSQ ) );
+}
+
+
+void ScInterpreter::ScSum()
+{
+    short nParamCount = GetByte();
+    double fRes = 0.0;
+    double fVal = 0.0;
+    ScAddress aAdr;
+    ScRange aRange;
+    size_t nRefInList = 0;
+    while (nParamCount-- > 0)
+    {
+        switch (GetStackType())
+        {
+            case svString:
+            {
+                while (nParamCount-- > 0)
+                    Pop();
+                SetError( errNoValue );
+            }
+            break;
+            case svDouble    :
+                fVal = GetDouble();
+                fRes += fVal;
+                nFuncFmtType = NUMBERFORMAT_NUMBER;
+                break;
+            case svExternalSingleRef:
+            {
+                ScExternalRefCache::TokenRef pToken;
+                ScExternalRefCache::CellFormat aFmt;
+                PopExternalSingleRef(pToken, &aFmt);
+
+                if (!pToken)
+                    break;
+
+                StackVar eType = pToken->GetType();
+                if (eType == formula::svDouble)
+                {
+                    fVal = pToken->GetDouble();
+                    if (aFmt.mbIsSet)
+                    {
+                        nFuncFmtType = aFmt.mnType;
+                        nFuncFmtIndex = aFmt.mnIndex;
+                    }
+
+                    fRes += fVal;
+                }
+            }
+            break;
+            case svSingleRef :
+            {
+                PopSingleRef( aAdr );
+
+                if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
+                {
+                    break;
+                }
+                ScRefCellValue aCell;
+                aCell.assign(*pDok, aAdr);
+                if (!aCell.isEmpty())
+                {
+                    if (aCell.hasNumeric())
+                    {
+                        fVal = GetCellValue(aAdr, aCell);
+                        CurFmtToFuncFmt();
+                        fRes += fVal;
+                    }
+                }
+            }
+            break;
+            case svDoubleRef :
+            case svRefList :
+            {
+                PopDoubleRef( aRange, nParamCount, nRefInList);
+
+                sc::ColumnSpanSet aSet(false);
+                aSet.set(aRange, true);
+                if (glSubTotal)
+                    // Skip all filtered rows and subtotal formula cells.
+                    pDok->MarkSubTotalCells(aSet, aRange, false);
+
+                FuncSum aAction;
+                aSet.executeColumnAction(*pDok, aAction);
+                fRes = aAction.getSum();
+
+                // Get the number format of the last iterated cell.
+                nFuncFmtIndex = aAction.getNumberFormat();
+                nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
+            }
+            break;
+            case svExternalDoubleRef:
+            {
+                ScMatrixRef pMat;
+                PopExternalDoubleRef(pMat);
+                if (nGlobalError)
+                    break;
+
+                sal_uLong nCount = 0;
+                double fMem = 0.0;
+                bool bNull = true;
+                IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
+                fRes += fMem;
+            }
+            break;
+            case svMatrix :
+            {
+                ScMatrixRef pMat = PopMatrix();
+                sal_uLong nCount = 0;
+                double fMem = 0.0;
+                bool bNull = true;
+                IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
+                fRes += fMem;
+            }
+            break;
+            case svError:
+            {
+                PopError();
+            }
+            break;
+            default :
+                while (nParamCount-- > 0)
+                    PopError();
+                SetError(errIllegalParameter);
+        }
+    }
+
+    if (nFuncFmtType == NUMBERFORMAT_LOGICAL)
+        nFuncFmtType = NUMBERFORMAT_NUMBER;
+
+    PushDouble(fRes);
+}
+
+
+void ScInterpreter::ScProduct()
+{
+    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScProduct" );
+    PushDouble( IterateParameters( ifPRODUCT ) );
+}
+
+
+void ScInterpreter::ScAverage( bool bTextAsZero )
+{
+    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAverage" );
+    PushDouble( IterateParameters( ifAVERAGE, bTextAsZero ) );
+}
+
+void ScInterpreter::ScCount()
+{
+    short nParamCount = GetByte();
+    double fVal = 0.0;
+    sal_uLong nCount = 0;
+    ScAddress aAdr;
+    ScRange aRange;
+    size_t nRefInList = 0;
+    if (nGlobalError)
+        nGlobalError = 0;
+
+    while (nParamCount-- > 0)
+    {
+        switch (GetStackType())
+        {
+            case svString:
+            {
+                String aStr( PopString() );
+                sal_uInt32 nFIndex = 0;                 // damit default Land/Spr.
+                if (pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
+                    nCount++;
+            }
+            break;
+            case svDouble    :
+                nCount++;
+                nFuncFmtType = NUMBERFORMAT_NUMBER;
+                break;
+            case svExternalSingleRef:
+            {
+                ScExternalRefCache::TokenRef pToken;
+                ScExternalRefCache::CellFormat aFmt;
+                PopExternalSingleRef(pToken, &aFmt);
+                if (nGlobalError)
+                {
+                    nGlobalError = 0;
+                    break;
+                }
+
+                if (!pToken)
+                    break;
+
+                StackVar eType = pToken->GetType();
+                if (eType == formula::svDouble)
+                {
+                    nCount++;
+                    if (aFmt.mbIsSet)
+                    {
+                        nFuncFmtType = aFmt.mnType;
+                        nFuncFmtIndex = aFmt.mnIndex;
+                    }
+
+                    if (nGlobalError)
+                    {
+                        nGlobalError = 0;
+                        nCount--;
+                    }
+                }
+            }
+            break;
+            case svSingleRef :
+            {
+                PopSingleRef( aAdr );
+                if (nGlobalError)
+                {
+                    nGlobalError = 0;
+                    break;
+                }
+                if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
+                {
+                    break;
+                }
+                ScRefCellValue aCell;
+                aCell.assign(*pDok, aAdr);
+                if (!aCell.isEmpty())
+                {
+                    if (aCell.hasNumeric())
+                    {
+                        nCount++;
+                        CurFmtToFuncFmt();
+                        if (nGlobalError)
+                        {
+                            nGlobalError = 0;
+                            nCount--;
+                        }
+                    }
+                }
+            }
+            break;
+            case svDoubleRef :
+            case svRefList :
+            {
+                PopDoubleRef( aRange, nParamCount, nRefInList);
+                if (nGlobalError)
+                {
+                    nGlobalError = 0;
+                    break;
+                }
+
+                sc::ColumnSpanSet aSet(false);
+                aSet.set(aRange, true);
+                if (glSubTotal)
+                    // Skip all filtered rows and subtotal formula cells.
+                    pDok->MarkSubTotalCells(aSet, aRange, false);
+
+                FuncCount aAction;
+                aSet.executeColumnAction(*pDok, aAction);
+                nCount = aAction.getCount();
+
+                // Get the number format of the last iterated cell.
+                nFuncFmtIndex = aAction.getNumberFormat();
+                nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
+            }
+            break;
+            case svExternalDoubleRef:
+            {
+                ScMatrixRef pMat;
+                PopExternalDoubleRef(pMat);
+                if (nGlobalError)
+                    break;
+
+                double fMem = 0.0, fRes = 0.0;
+                bool bNull = true;
+                IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
+            }
+            break;
+            case svMatrix :
+            {
+                ScMatrixRef pMat = PopMatrix();
+                double fMem = 0.0, fRes = 0.0;
+                bool bNull = true;
+                IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
+            }
+            break;
+            case svError:
+            {
+                PopError();
+                nGlobalError = 0;
+            }
+            break;
+            default :
+                while (nParamCount-- > 0)
+                    PopError();
+                SetError(errIllegalParameter);
+        }
+    }
+
+    nFuncFmtType = NUMBERFORMAT_NUMBER;
+
+    PushDouble(nCount);
+}
+
+
+void ScInterpreter::ScCount2()
+{
+    RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCount2" );
+    PushDouble( IterateParameters( ifCOUNT2 ) );
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list