summaryrefslogtreecommitdiff
path: root/sc/source/core
diff options
context:
space:
mode:
authordante <dante19031999@gmail.com>2021-05-04 21:06:19 +0200
committerMike Kaganski <mike.kaganski@collabora.com>2021-05-05 07:15:51 +0200
commit36f35bd823ef9af454f1d4609ad302acbef0709b (patch)
treeab4c03b61fcef41bef6628b685c2d53e593f8fe0 /sc/source/core
parentef78c7d93e4f170ac7a7f0307a8305052524eb53 (diff)
Use kahan Sum for ArraySumFunctor
Change-Id: I2f00d3c4c04f1c65083137d36772728a1eae0bed Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115112 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'sc/source/core')
-rw-r--r--sc/source/core/inc/arraysumfunctor.hxx25
1 files changed, 14 insertions, 11 deletions
diff --git a/sc/source/core/inc/arraysumfunctor.hxx b/sc/source/core/inc/arraysumfunctor.hxx
index 62847493b88a..ae8d38db1338 100644
--- a/sc/source/core/inc/arraysumfunctor.hxx
+++ b/sc/source/core/inc/arraysumfunctor.hxx
@@ -17,6 +17,7 @@
#include <sal/types.h>
#include <tools/simd.hxx>
#include <tools/cpuid.hxx>
+#include <kahan.hxx>
namespace sc
{
@@ -33,11 +34,11 @@ public:
{
}
- double operator()()
+ KahanSum operator()()
{
const static bool hasSSE2 = cpuid::hasSSE2();
- double fSum = 0.0;
+ KahanSum fSum = 0.0;
size_t i = 0;
const double* pCurrent = mpArray;
@@ -54,7 +55,7 @@ public:
}
}
else
- fSum += executeUnrolled(i, pCurrent);
+ fSum = executeUnrolled(i, pCurrent);
// sum rest of the array
@@ -63,9 +64,10 @@ public:
// If the sum is a NaN, some of the terms were empty cells, probably.
// Re-calculate, carefully
- if (!std::isfinite(fSum))
+ double fVal = fSum.get();
+ if (!std::isfinite(fVal))
{
- sal_uInt32 nErr = reinterpret_cast<sal_math_Double*>(&fSum)->nan_parts.fraction_lo;
+ sal_uInt32 nErr = reinterpret_cast<sal_math_Double*>(&fVal)->nan_parts.fraction_lo;
if (nErr & 0xffff0000)
{
fSum = 0;
@@ -88,17 +90,17 @@ public:
private:
double executeSSE2(size_t& i, const double* pCurrent) const;
- double executeUnrolled(size_t& i, const double* pCurrent) const
+ KahanSum executeUnrolled(size_t& i, const double* pCurrent) const
{
size_t nRealSize = mnSize - i;
size_t nUnrolledSize = nRealSize - (nRealSize % 4);
if (nUnrolledSize > 0)
{
- double sum0 = 0.0;
- double sum1 = 0.0;
- double sum2 = 0.0;
- double sum3 = 0.0;
+ KahanSum sum0 = 0.0;
+ KahanSum sum1 = 0.0;
+ KahanSum sum2 = 0.0;
+ KahanSum sum3 = 0.0;
for (; i < nUnrolledSize; i += 4)
{
@@ -107,7 +109,8 @@ private:
sum2 += *pCurrent++;
sum3 += *pCurrent++;
}
- return sum0 + sum1 + sum2 + sum3;
+ // We are using pairwise summation alongside Kahan
+ return (sum0 + sum1) + (sum2 + sum3);
}
return 0.0;
}