sc/inc/columnspanset.hxx                |    2 
 sc/inc/matrixoperators.hxx              |    7 -
 sc/inc/scmatrix.hxx                     |   21 +++-
 sc/qa/uitest/calc_tests6/tdf118638.py   |    4 
 sc/source/core/data/columnspanset.cxx   |   21 ----
 sc/source/core/tool/interpr5.cxx        |    4 
 sc/source/core/tool/interpr6.cxx        |  160 ++++++++------------------------
 sc/source/core/tool/matrixoperators.cxx |   19 ---
 sc/source/core/tool/scmatrix.cxx        |   48 +++------
 solenv/clang-format/excludelist         |    1 
 10 files changed, 86 insertions(+), 201 deletions(-)

New commits:
commit fd4df675dfe1012448285134082f61a0c03a7d15
Author:     dante <dante19031...@gmail.com>
AuthorDate: Sun Apr 25 12:20:58 2021 +0200
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Apr 28 16:31:45 2021 +0200

    tdf#137679 Use Kahan summation for scmatrix operations
    
    May also want implement Kahan sum in there:
    sc/source/core/tool/arraysumSSE2.cxx
    sc/source/core/inc/arraysumfunctor.hxx
    Under some conditions the sum of a pointer type vector
    may be perforemed by arraysumfunctor on NumericCellAccumulator.
    arraysumSSE2 implements part of it.
    This code has been left unmodified.
    
    Why the test has been modified:
    The error was: 238.89000000000001 != 238.89
                                    |
                                    17 th digit
    IEEE 754 double-precision has 53 log10(2) ≈ 15.955 digits.
    So it's just noise.
    
    Change-Id: I6f84826bf3875be4f444f5eb61854bc1f95769bb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114627
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins

diff --git a/sc/inc/columnspanset.hxx b/sc/inc/columnspanset.hxx
index 570f99c10fb8..d889a4da67e4 100644
--- a/sc/inc/columnspanset.hxx
+++ b/sc/inc/columnspanset.hxx
@@ -80,7 +80,6 @@ public:
         virtual ~ColumnAction() = 0;
         virtual void startColumn(ScColumn* pCol) = 0;
         virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal) = 0;
-        virtual void executeSum(SCROW, SCROW, bool, double& )  { return; } ;
     };
 
     ColumnSpanSet();
@@ -162,7 +161,6 @@ public:
     RangeColumnSpanSet( const ScRange& spanRange )
          : range( spanRange ) {}
     void executeColumnAction(ScDocument& rDoc, 
sc::ColumnSpanSet::ColumnAction& ac) const;
-    void executeColumnAction(ScDocument& rDoc, 
sc::ColumnSpanSet::ColumnAction& ac, double& fMem) const;
 private:
     ScRange range;
 };
diff --git a/sc/inc/matrixoperators.hxx b/sc/inc/matrixoperators.hxx
index 540a38e93370..36fa1cabe3d6 100644
--- a/sc/inc/matrixoperators.hxx
+++ b/sc/inc/matrixoperators.hxx
@@ -11,6 +11,7 @@
 
 
 #include <functional>
+#include "math.hxx"
 
 namespace sc::op {
 
@@ -35,19 +36,19 @@ using Op = Op_<std::function<void(double&, double)>>;
 struct Sum
 {
     static const double InitVal;
-    void operator()(double& rAccum, double fVal) const;
+    void operator()(KahanSum& rAccum, double fVal) const;
 };
 
 struct SumSquare
 {
     static const double InitVal;
-    void operator()(double& rAccum, double fVal) const;
+    void operator()(KahanSum& rAccum, double fVal) const;
 };
 
 struct Product
 {
     static const double InitVal;
-    void operator()(double& rAccum, double fVal) const;
+    void operator()(KahanSum& rAccum, double fVal) const;
 };
 
 }
diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index 60587b23a5d1..2a1d9342499f 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -150,6 +150,21 @@ public:
             mfFirst(fFirst), mfRest(fRest), mnCount(nCount) {}
     };
 
+    /**
+      * Version of IterateResult for using Kahan sum.
+      */
+    struct KahanIterateResult
+    {
+        KahanSum maAccumulator;
+        size_t mnCount;
+
+        KahanIterateResult(double fAccumulator, size_t nCount)
+            : maAccumulator(fAccumulator), mnCount(nCount) {}
+
+        double get() { return maAccumulator.get(); }
+    };
+
+
     /** Checks nC or nR for zero and uses GetElementsMax() whether a matrix of
         the size of nC*nR could be allocated. A zero size (both nC and nR zero)
         matrix is allowed for later resize.
@@ -361,9 +376,9 @@ public:
     double Or() const ;        // logical OR of all matrix values, or NAN
     double Xor() const ;       // logical XOR of all matrix values, or NAN
 
-    IterateResult Sum( bool bTextAsZero, bool bIgnoreErrorValues = false ) 
const ;
-    IterateResult SumSquare( bool bTextAsZero, bool bIgnoreErrorValues = false 
) const ;
-    IterateResult Product( bool bTextAsZero, bool bIgnoreErrorValues = false ) 
const ;
+    KahanIterateResult Sum( bool bTextAsZero, bool bIgnoreErrorValues = false 
) const ;
+    KahanIterateResult SumSquare( bool bTextAsZero, bool bIgnoreErrorValues = 
false ) const ;
+    KahanIterateResult Product( bool bTextAsZero, bool bIgnoreErrorValues = 
false ) const ;
     size_t Count(bool bCountStrings, bool bCountErrors, bool 
bIgnoreEmptyStrings = false) const ;
     size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) 
const ;
     size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, 
size_t nCol2) const ;
diff --git a/sc/qa/uitest/calc_tests6/tdf118638.py 
b/sc/qa/uitest/calc_tests6/tdf118638.py
index 2e1b704a82d9..cc5c97f34a30 100644
--- a/sc/qa/uitest/calc_tests6/tdf118638.py
+++ b/sc/qa/uitest/calc_tests6/tdf118638.py
@@ -47,8 +47,8 @@ class Subtotals(UITestCase):
         self.assertEqual(get_cell_by_position(document, 0, 0, 15).getString(), 
"5408 Sum")
         self.assertEqual(get_cell_by_position(document, 0, 0, 16).getString(), 
"Grand Sum")
 
-        self.assertEqual(get_cell_by_position(document, 0, 1, 15).getValue(), 
238.89)
-        self.assertEqual(get_cell_by_position(document, 0, 1, 16).getValue(), 
238.89)
+        self.assertEqual(round(get_cell_by_position(document, 0, 1, 
15).getValue(),12), 238.89)
+        self.assertEqual(round(get_cell_by_position(document, 0, 1, 
16).getValue(),12), 238.89)
 
         self.assertEqual(get_cell_by_position(document, 0, 1, 15).getString(), 
"$238.89")
         self.assertEqual(get_cell_by_position(document, 0, 1, 16).getString(), 
"$238.89")
diff --git a/sc/source/core/data/columnspanset.cxx 
b/sc/source/core/data/columnspanset.cxx
index fe9b55193d6f..b400cd651c5a 100644
--- a/sc/source/core/data/columnspanset.cxx
+++ b/sc/source/core/data/columnspanset.cxx
@@ -359,27 +359,6 @@ void RangeColumnSpanSet::executeColumnAction(ScDocument& 
rDoc, sc::ColumnSpanSet
     }
 }
 
-void RangeColumnSpanSet::executeColumnAction(ScDocument& rDoc, 
sc::ColumnSpanSet::ColumnAction& ac, double& fMem) const
-{
-    for (SCTAB nTab = range.aStart.Tab(); nTab <= range.aEnd.Tab(); ++nTab)
-    {
-        ScTable* pTab = rDoc.FetchTable(nTab);
-        if (!pTab)
-            continue;
-
-        SCCOL nEndCol = pTab->ClampToAllocatedColumns(range.aEnd.Col());
-        for (SCCOL nCol = range.aStart.Col(); nCol <= nEndCol; ++nCol)
-        {
-            if (!rDoc.ValidCol(nCol))
-                break;
-
-            ScColumn& rColumn = pTab->aCol[nCol];
-            ac.startColumn(&rColumn);
-            ac.executeSum( range.aStart.Row(), range.aEnd.Row(), true, fMem );
-        }
-    }
-}
-
 } // namespace sc
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index 4cf5d9ce4339..0fe64d647bfe 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -1871,9 +1871,7 @@ void ScInterpreter::ScSumXMY2()
     }
     else
     {
-        ScMatrix::IterateResult aRes = pResMat->SumSquare(false);
-        double fSum = aRes.mfFirst + aRes.mfRest;
-        PushDouble(fSum);
+        PushDouble(pResMat->SumSquare(false).get());
     }
 }
 
diff --git a/sc/source/core/tool/interpr6.cxx b/sc/source/core/tool/interpr6.cxx
index f506b9f04753..a48d7d3ad77b 100644
--- a/sc/source/core/tool/interpr6.cxx
+++ b/sc/source/core/tool/interpr6.cxx
@@ -207,12 +207,11 @@ namespace {
 
 class NumericCellAccumulator
 {
-    double mfFirst;
-    double mfRest;
+    KahanSum maSum;
     FormulaError mnError;
 
 public:
-    NumericCellAccumulator() : mfFirst(0.0), mfRest(0.0), 
mnError(FormulaError::NONE) {}
+    NumericCellAccumulator() : maSum(0.0), mnError(FormulaError::NONE) {}
 
     void operator() (const sc::CellStoreType::value_type& rNode, size_t 
nOffset, size_t nDataSize)
     {
@@ -220,28 +219,13 @@ public:
         {
             case sc::element_type_numeric:
             {
-                const double *p = &sc::numeric_block::at(*rNode.data, nOffset);
-                size_t i = 0;
-
-                // Store the first non-zero value in mfFirst (for some reason).
-                if (!mfFirst)
-                {
-                    for (i = 0; i < nDataSize; ++i)
-                    {
-                        if (!mfFirst)
-                            mfFirst = p[i];
-                        else
-                            break;
-                    }
-                }
-                p += i;
-                nDataSize -= i;
                 if (nDataSize == 0)
                     return;
 
+                const double *p = &sc::numeric_block::at(*rNode.data, nOffset);
                 sc::ArraySumFunctor functor(p, nDataSize);
 
-                mfRest += functor();
+                maSum += functor();
                 break;
             }
 
@@ -267,10 +251,7 @@ public:
                         return;
                     }
 
-                    if ( !mfFirst )
-                        mfFirst = fVal;
-                    else
-                        mfRest += fVal;
+                    maSum += fVal;
                 }
             }
             break;
@@ -280,8 +261,7 @@ public:
     }
 
     FormulaError getError() const { return mnError; }
-    double getFirst() const { return mfFirst; }
-    double getRest() const { return mfRest; }
+    KahanSum getResult() const { return maSum; }
 };
 
 class NumericCellCounter
@@ -356,7 +336,7 @@ class FuncSum : public sc::ColumnSpanSet::ColumnAction
     const ScInterpreterContext& mrContext;
     sc::ColumnBlockConstPosition maPos;
     ScColumn* mpCol;
-    double mfSum;
+    KahanSum mfSum;
     FormulaError mnError;
     sal_uInt32 mnNumFmt;
 
@@ -369,9 +349,7 @@ public:
         mpCol->InitBlockPosition(maPos);
     }
 
-    virtual void execute(SCROW, SCROW, bool) override {}
-
-    virtual void executeSum(SCROW nRow1, SCROW nRow2, bool bVal, double& fMem 
) override
+    virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal) override
     {
         if (!bVal)
             return;
@@ -385,19 +363,13 @@ public:
         if (mnError != FormulaError::NONE)
             return;
 
-        if ( fMem )
-            mfSum += aFunc.getFirst() + aFunc.getRest();
-        else
-        {
-            fMem = aFunc.getFirst();
-            mfSum += aFunc.getRest();
-        }
 
+        mfSum += aFunc.getResult();
         mnNumFmt = mpCol->GetNumberFormat(mrContext, nRow2);
     };
 
     FormulaError getError() const { return mnError; }
-    double getSum() const { return mfSum; }
+    KahanSum getSum() const { return mfSum; }
     sal_uInt32 getNumberFormat() const { return mnNumFmt; }
 };
 
@@ -405,7 +377,7 @@ public:
 
 static void IterateMatrix(
     const ScMatrixRef& pMat, ScIterFunc eFunc, bool bTextAsZero, SubtotalFlags 
nSubTotalFlags,
-    sal_uLong& rCount, SvNumFormatType& rFuncFmtType, double& fRes, double& 
fMem )
+    sal_uLong& rCount, SvNumFormatType& rFuncFmtType, KahanSum& fRes )
 {
     if (!pMat)
         return;
@@ -417,24 +389,8 @@ static void IterateMatrix(
         case ifAVERAGE:
         case ifSUM:
         {
-            ScMatrix::IterateResult aRes = pMat->Sum(bTextAsZero, 
bIgnoreErrVal);
-            // If the first value is a NaN, it probably means it was an empty 
cell,
-            // and should be treated as zero.
-            if ( !std::isfinite(aRes.mfFirst) )
-            {
-                sal_uInt32 nErr = reinterpret_cast< sal_math_Double * 
>(&aRes.mfFirst)->nan_parts.fraction_lo;
-                if (nErr & 0xffff0000)
-                {
-                    aRes.mfFirst = 0;
-                }
-            }
-            if ( fMem )
-                fRes += aRes.mfFirst + aRes.mfRest;
-            else
-            {
-                fMem = aRes.mfFirst;
-                fRes += aRes.mfRest;
-            }
+            ScMatrix::KahanIterateResult aRes = pMat->Sum(bTextAsZero, 
bIgnoreErrVal);
+            fRes += aRes.maAccumulator;
             rCount += aRes.mnCount;
         }
         break;
@@ -447,17 +403,15 @@ static void IterateMatrix(
         break;
         case ifPRODUCT:
         {
-            ScMatrix::IterateResult aRes = pMat->Product(bTextAsZero, 
bIgnoreErrVal);
-            fRes *= aRes.mfFirst;
-            fRes *= aRes.mfRest;
+            ScMatrix::KahanIterateResult aRes = pMat->Product(bTextAsZero, 
bIgnoreErrVal);
+            fRes *= aRes.get();
             rCount += aRes.mnCount;
         }
         break;
         case ifSUMSQ:
         {
-            ScMatrix::IterateResult aRes = pMat->SumSquare(bTextAsZero, 
bIgnoreErrVal);
-            fRes += aRes.mfFirst;
-            fRes += aRes.mfRest;
+            ScMatrix::KahanIterateResult aRes = pMat->SumSquare(bTextAsZero, 
bIgnoreErrVal);
+            fRes += aRes.maAccumulator;
             rCount += aRes.mnCount;
         }
         break;
@@ -484,15 +438,12 @@ size_t ScInterpreter::GetRefListArrayMaxSize( short 
nParamCount )
     return nSize;
 }
 
-static double lcl_IterResult( ScIterFunc eFunc, double fRes, double fMem, 
sal_uLong nCount )
+static double lcl_IterResult( ScIterFunc eFunc, double fRes, sal_uLong nCount )
 {
     switch( eFunc )
     {
-        case ifSUM:
-            fRes = ::rtl::math::approxAdd( fRes, fMem );
-        break;
         case ifAVERAGE:
-            fRes = sc::div( ::rtl::math::approxAdd( fRes, fMem ), nCount);
+            fRes = sc::div( fRes, nCount);
         break;
         case ifCOUNT2:
         case ifCOUNT:
@@ -514,9 +465,8 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, 
bool bTextAsZero )
     const SCSIZE nMatRows = GetRefListArrayMaxSize( nParamCount);
     ScMatrixRef xResMat, xResCount;
     const double ResInitVal = (eFunc == ifPRODUCT) ? 1.0 : 0.0;
-    double fRes = ResInitVal;
+    KahanSum fRes = ResInitVal;
     double fVal = 0.0;
-    double fMem = 0.0;  // first numeric value != 0.0
     sal_uLong nCount = 0;
     ScAddress aAdr;
     ScRange aRange;
@@ -584,12 +534,7 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, 
bool bTextAsZero )
                 switch( eFunc )
                 {
                     case ifAVERAGE:
-                    case ifSUM:
-                        if ( fMem )
-                            fRes += fVal;
-                        else
-                            fMem = fVal;
-                        break;
+                    case ifSUM:     fRes += fVal; break;
                     case ifSUMSQ:   fRes += fVal * fVal; break;
                     case ifPRODUCT: fRes *= fVal; break;
                     default: ; // nothing
@@ -636,12 +581,7 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, 
bool bTextAsZero )
                     switch( eFunc )
                     {
                         case ifAVERAGE:
-                        case ifSUM:
-                            if ( fMem )
-                                fRes += fVal;
-                            else
-                                fMem = fVal;
-                            break;
+                        case ifSUM:     fRes += fVal; break;
                         case ifSUMSQ:   fRes += fVal * fVal; break;
                         case ifPRODUCT: fRes *= fVal; break;
                         case ifCOUNT:
@@ -705,12 +645,7 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, 
bool bTextAsZero )
                         switch( eFunc )
                         {
                             case ifAVERAGE:
-                            case ifSUM:
-                                if ( fMem )
-                                    fRes += fVal;
-                                else
-                                    fMem = fVal;
-                                break;
+                            case ifSUM:     fRes += fVal; break;
                             case ifSUMSQ:   fRes += fVal * fVal; break;
                             case ifPRODUCT: fRes *= fVal; break;
                             case ifCOUNT:
@@ -738,11 +673,6 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, 
bool bTextAsZero )
                 if (p && p->IsArrayResult())
                 {
                     nRefArrayPos = nRefInList;
-                    if ((eFunc == ifSUM || eFunc == ifAVERAGE) && fMem != 0.0)
-                    {
-                        fRes = rtl::math::approxAdd( fRes, fMem);
-                        fMem = 0.0;
-                    }
                     // The "one value to all references of an array" seems to
                     // be what Excel does if there are other types than just
                     // arrays of references.
@@ -751,7 +681,7 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, 
bool bTextAsZero )
                         // Create and init all elements with current value.
                         assert(nMatRows > 0);
                         xResMat = GetNewMat( 1, nMatRows, true);
-                        xResMat->FillDouble( fRes, 0,0, 0,nMatRows-1);
+                        xResMat->FillDouble( fRes.get(), 0,0, 0,nMatRows-1);
                         if (eFunc != ifSUM)
                         {
                             xResCount = GetNewMat( 1, nMatRows, true);
@@ -775,9 +705,9 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, 
bool bTextAsZero )
                             {
                                 double fVecRes = xResMat->GetDouble(0,i);
                                 if (eFunc == ifPRODUCT)
-                                    fVecRes *= fRes;
+                                    fVecRes *= fRes.get();
                                 else
-                                    fVecRes += fRes;
+                                    fVecRes += fRes.get();
                                 xResMat->PutDouble( fVecRes, 0,i);
                             }
                         }
@@ -830,7 +760,7 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, 
bool bTextAsZero )
                     if ( eFunc == ifSUM )
                     {
                         FuncSum aAction(mrContext);
-                        aSet.executeColumnAction( mrDoc, aAction, fMem );
+                        aSet.executeColumnAction( mrDoc, aAction );
                         FormulaError nErr = aAction.getError();
                         if ( nErr != FormulaError::NONE )
                         {
@@ -874,10 +804,7 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, 
bool bTextAsZero )
                                             if ( nErr == FormulaError::NONE )
                                             {
                                                 SetError(nErr);
-                                                if ( fMem )
-                                                    fRes += fVal;
-                                                else
-                                                    fMem = fVal;
+                                                fRes += fVal;
                                                 nCount++;
                                             }
                                         }
@@ -888,10 +815,7 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, 
bool bTextAsZero )
                                         do
                                         {
                                             SetError(nErr);
-                                            if ( fMem )
-                                                fRes += fVal;
-                                            else
-                                                fMem = fVal;
+                                            fRes += fVal;
                                             nCount++;
                                         }
                                         while (aValIter.GetNext(fVal, nErr));
@@ -950,18 +874,13 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, 
bool bTextAsZero )
                 if (nRefArrayPos != std::numeric_limits<size_t>::max())
                 {
                     // Update vector element with current value.
-                    if ((eFunc == ifSUM || eFunc == ifAVERAGE) && fMem != 0.0)
-                    {
-                        fRes = rtl::math::approxAdd( fRes, fMem);
-                        fMem = 0.0;
-                    }
                     if (xResCount)
                         xResCount->PutDouble( 
xResCount->GetDouble(0,nRefArrayPos) + nCount, 0,nRefArrayPos);
                     double fVecRes = xResMat->GetDouble(0,nRefArrayPos);
                     if (eFunc == ifPRODUCT)
-                        fVecRes *= fRes;
+                        fVecRes *= fRes.get();
                     else
-                        fVecRes += fRes;
+                        fVecRes += fRes.get();
                     xResMat->PutDouble( fVecRes, 0,nRefArrayPos);
                     // Reset.
                     fRes = ResInitVal;
@@ -977,14 +896,14 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, 
bool bTextAsZero )
                 if ( nGlobalError != FormulaError::NONE && !( mnSubTotalFlags 
& SubtotalFlags::IgnoreErrVal ) )
                     break;
 
-                IterateMatrix( pMat, eFunc, bTextAsZero, mnSubTotalFlags, 
nCount, nFuncFmtType, fRes, fMem );
+                IterateMatrix( pMat, eFunc, bTextAsZero, mnSubTotalFlags, 
nCount, nFuncFmtType, fRes );
             }
             break;
             case svMatrix :
             {
                 ScMatrixRef pMat = PopMatrix();
 
-                IterateMatrix( pMat, eFunc, bTextAsZero, mnSubTotalFlags, 
nCount, nFuncFmtType, fRes, fMem );
+                IterateMatrix( pMat, eFunc, bTextAsZero, mnSubTotalFlags, 
nCount, nFuncFmtType, fRes );
             }
             break;
             case svError:
@@ -1021,17 +940,17 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, 
bool bTextAsZero )
             sal_uLong nVecCount = (xResCount ? nCount + 
xResCount->GetDouble(0,i) : nCount);
             double fVecRes = xResMat->GetDouble(0,i);
             if (eFunc == ifPRODUCT)
-                fVecRes *= fRes;
+                fVecRes *= fRes.get();
             else
-                fVecRes += fRes;
-            fVecRes = lcl_IterResult( eFunc, fVecRes, fMem, nVecCount);
+                fVecRes += fRes.get();
+            fVecRes = lcl_IterResult( eFunc, fVecRes, nVecCount);
             xResMat->PutDouble( fVecRes, 0,i);
         }
         PushMatrix( xResMat);
     }
     else
     {
-        PushDouble( lcl_IterResult( eFunc, fRes, fMem, nCount));
+        PushDouble( lcl_IterResult( eFunc, fRes.get(), nCount));
     }
 }
 
@@ -1065,6 +984,11 @@ void ScInterpreter::ScCount2()
     IterateParameters( ifCOUNT2 );
 }
 
+/**
+ * The purpose of RAWSUBTRACT() is exactly to not apply any error correction, 
approximation etc.
+ * But use the "raw" IEEE 754 double subtraction.
+ * So no Kahan summation
+ */
 void ScInterpreter::ScRawSubtract()
 {
     short nParamCount = GetByte();
diff --git a/sc/source/core/tool/matrixoperators.cxx 
b/sc/source/core/tool/matrixoperators.cxx
index 31cf6d96b2df..e65d4d7c0dc2 100644
--- a/sc/source/core/tool/matrixoperators.cxx
+++ b/sc/source/core/tool/matrixoperators.cxx
@@ -9,30 +9,19 @@
 
 #include <matrixoperators.hxx>
 
-
-namespace sc::op {
-
-void Sum::operator()(double& rAccum, double fVal) const
+namespace sc::op
 {
-    rAccum += fVal;
-}
+void Sum::operator()(KahanSum& rAccum, double fVal) const { rAccum += fVal; }
 
 const double Sum::InitVal = 0.0;
 
-void SumSquare::operator()(double& rAccum, double fVal) const
-{
-    rAccum += fVal * fVal;
-}
+void SumSquare::operator()(KahanSum& rAccum, double fVal) const { rAccum += 
fVal * fVal; }
 
 const double SumSquare::InitVal = 0.0;
 
-void Product::operator()(double& rAccum, double fVal) const
-{
-    rAccum *= fVal;
-}
+void Product::operator()(KahanSum& rAccum, double fVal) const { rAccum *= 
fVal; }
 
 const double Product::InitVal = 1.0;
-
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index ad7f4c788df7..a10863ea3a53 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -302,9 +302,9 @@ public:
     double Or() const;
     double Xor() const;
 
-    ScMatrix::IterateResult Sum( bool bTextAsZero, bool bIgnoreErrorValues ) 
const;
-    ScMatrix::IterateResult SumSquare( bool bTextAsZero, bool 
bIgnoreErrorValues ) const;
-    ScMatrix::IterateResult Product( bool bTextAsZero, bool bIgnoreErrorValues 
) const;
+    ScMatrix::KahanIterateResult Sum( bool bTextAsZero, bool 
bIgnoreErrorValues ) const;
+    ScMatrix::KahanIterateResult SumSquare( bool bTextAsZero, bool 
bIgnoreErrorValues ) const;
+    ScMatrix::KahanIterateResult Product( bool bTextAsZero, bool 
bIgnoreErrorValues ) const;
     size_t Count(bool bCountStrings, bool bCountErrors, bool 
bIgnoreEmptyStrings) const;
     size_t MatchDoubleInColumns(double fValue, size_t nCol1, size_t nCol2) 
const;
     size_t MatchStringInColumns(const svl::SharedString& rStr, size_t nCol1, 
size_t nCol2) const;
@@ -1111,17 +1111,16 @@ template<typename Op>
 class WalkElementBlocks
 {
     Op maOp;
-    ScMatrix::IterateResult maRes;
-    bool mbFirst:1;
+    ScMatrix::KahanIterateResult maRes;
     bool mbTextAsZero:1;
     bool mbIgnoreErrorValues:1;
 public:
     WalkElementBlocks(bool bTextAsZero, bool bIgnoreErrorValues) :
-        maRes(Op::InitVal, Op::InitVal, 0), mbFirst(true),
+        maRes(Op::InitVal, 0),
         mbTextAsZero(bTextAsZero), mbIgnoreErrorValues(bIgnoreErrorValues)
     {}
 
-    const ScMatrix::IterateResult& getResult() const { return maRes; }
+    const ScMatrix::KahanIterateResult& getResult() const { return maRes; }
 
     void operator() (const MatrixImplType::element_block_node_type& node)
     {
@@ -1141,16 +1140,7 @@ public:
                         ++nIgnored;
                         continue;
                     }
-
-                    if (mbFirst)
-                    {
-                        maOp(maRes.mfFirst, *it);
-                        mbFirst = false;
-                    }
-                    else
-                    {
-                        maOp(maRes.mfRest, *it);
-                    }
+                    maOp(maRes.maAccumulator, *it);
                 }
                 maRes.mnCount += node.size - nIgnored;
             }
@@ -1163,15 +1153,7 @@ public:
                 block_type::const_iterator itEnd = block_type::end(*node.data);
                 for (; it != itEnd; ++it)
                 {
-                    if (mbFirst)
-                    {
-                        maOp(maRes.mfFirst, *it);
-                        mbFirst = false;
-                    }
-                    else
-                    {
-                        maOp(maRes.mfRest, *it);
-                    }
+                    maOp(maRes.maAccumulator, *it);
                 }
                 maRes.mnCount += node.size;
             }
@@ -2099,7 +2081,7 @@ public:
 namespace {
 
 template<typename TOp>
-ScMatrix::IterateResult GetValueWithCount(bool bTextAsZero, bool 
bIgnoreErrorValues, const MatrixImplType& maMat)
+ScMatrix::KahanIterateResult GetValueWithCount(bool bTextAsZero, bool 
bIgnoreErrorValues, const MatrixImplType& maMat)
 {
     WalkElementBlocks<TOp> aFunc(bTextAsZero, bIgnoreErrorValues);
     aFunc = maMat.walk(aFunc);
@@ -2108,17 +2090,17 @@ ScMatrix::IterateResult GetValueWithCount(bool 
bTextAsZero, bool bIgnoreErrorVal
 
 }
 
-ScMatrix::IterateResult ScMatrixImpl::Sum(bool bTextAsZero, bool 
bIgnoreErrorValues) const
+ScMatrix::KahanIterateResult ScMatrixImpl::Sum(bool bTextAsZero, bool 
bIgnoreErrorValues) const
 {
     return GetValueWithCount<sc::op::Sum>(bTextAsZero, bIgnoreErrorValues, 
maMat);
 }
 
-ScMatrix::IterateResult ScMatrixImpl::SumSquare(bool bTextAsZero, bool 
bIgnoreErrorValues) const
+ScMatrix::KahanIterateResult ScMatrixImpl::SumSquare(bool bTextAsZero, bool 
bIgnoreErrorValues) const
 {
     return GetValueWithCount<sc::op::SumSquare>(bTextAsZero, 
bIgnoreErrorValues, maMat);
 }
 
-ScMatrix::IterateResult ScMatrixImpl::Product(bool bTextAsZero, bool 
bIgnoreErrorValues) const
+ScMatrix::KahanIterateResult ScMatrixImpl::Product(bool bTextAsZero, bool 
bIgnoreErrorValues) const
 {
     return GetValueWithCount<sc::op::Product>(bTextAsZero, bIgnoreErrorValues, 
maMat);
 }
@@ -3226,17 +3208,17 @@ double ScMatrix::Xor() const
     return pImpl->Xor();
 }
 
-ScMatrix::IterateResult ScMatrix::Sum(bool bTextAsZero, bool 
bIgnoreErrorValues) const
+ScMatrix::KahanIterateResult ScMatrix::Sum(bool bTextAsZero, bool 
bIgnoreErrorValues) const
 {
     return pImpl->Sum(bTextAsZero, bIgnoreErrorValues);
 }
 
-ScMatrix::IterateResult ScMatrix::SumSquare(bool bTextAsZero, bool 
bIgnoreErrorValues) const
+ScMatrix::KahanIterateResult ScMatrix::SumSquare(bool bTextAsZero, bool 
bIgnoreErrorValues) const
 {
     return pImpl->SumSquare(bTextAsZero, bIgnoreErrorValues);
 }
 
-ScMatrix::IterateResult ScMatrix::Product(bool bTextAsZero, bool 
bIgnoreErrorValues) const
+ScMatrix::KahanIterateResult ScMatrix::Product(bool bTextAsZero, bool 
bIgnoreErrorValues) const
 {
     return pImpl->Product(bTextAsZero, bIgnoreErrorValues);
 }
diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist
index 99d83dcc8730..927c1ceb781a 100644
--- a/solenv/clang-format/excludelist
+++ b/solenv/clang-format/excludelist
@@ -8311,7 +8311,6 @@ sc/source/core/tool/interpr8.cxx
 sc/source/core/tool/jumpmatrix.cxx
 sc/source/core/tool/listenerquery.cxx
 sc/source/core/tool/lookupcache.cxx
-sc/source/core/tool/matrixoperators.cxx
 sc/source/core/tool/navicfg.cxx
 sc/source/core/tool/numformat.cxx
 sc/source/core/tool/odffmap.cxx
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to