bump product version to 7.6.3.2-android
[LibreOffice.git] / sc / inc / arraysumfunctor.hxx
blobc1eabb220e2793d6a88c65d9afaf78069ba658e5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 */
11 #pragma once
13 #include <cmath>
14 #include "kahan.hxx"
15 #include <formula/errorcodes.hxx>
17 namespace sc::op
19 /**
20 * If no boosts available, Unrolled KahanSum.
22 static inline KahanSum executeUnrolled(size_t& i, size_t nSize, const double* pCurrent)
24 size_t nRealSize = nSize - i;
25 size_t nUnrolledSize = nRealSize - (nRealSize % 4);
27 if (nUnrolledSize > 0)
29 KahanSum sum0 = 0.0;
30 KahanSum sum1 = 0.0;
31 KahanSum sum2 = 0.0;
32 KahanSum sum3 = 0.0;
34 for (; i + 3 < nUnrolledSize; i += 4)
36 sum0 += *pCurrent++;
37 sum1 += *pCurrent++;
38 sum2 += *pCurrent++;
39 sum3 += *pCurrent++;
41 // We are using pairwise summation alongside Kahan
42 return (sum0 + sum1) + (sum2 + sum3);
44 return 0.0;
47 /**
48 * This function task is to choose the fastest method available to perform the sum.
49 * @param i
50 * @param nSize
51 * @param pCurrent
53 static inline KahanSum executeFast(size_t& i, size_t nSize, const double* pCurrent)
55 #if SC_USE_SSE2
56 return executeSSE2(i, nSize, pCurrent);
57 #else
58 return executeUnrolled(i, nSize, pCurrent);
59 #endif
62 /**
63 * Performs the sum of an array.
64 * Note that align 16 will speed up the process.
65 * @param pArray
66 * @param nSize
68 inline KahanSum sumArray(const double* pArray, size_t nSize)
70 size_t i = 0;
71 const double* pCurrent = pArray;
72 KahanSum fSum = executeFast(i, nSize, pCurrent);
74 // sum rest of the array
75 for (; i < nSize; ++i)
76 fSum += pArray[i];
78 // If the sum is a NaN, some of the terms were empty cells, probably.
79 // Re-calculate, carefully
80 double fVal = fSum.get();
81 if (!std::isfinite(fVal))
83 FormulaError nErr = GetDoubleErrorValue(fVal);
84 if (nErr == FormulaError::NoValue)
86 fSum = 0;
87 for (i = 0; i < nSize; i++)
89 if (!std::isfinite(pArray[i]))
91 nErr = GetDoubleErrorValue(pArray[i]);
92 if (nErr != FormulaError::NoValue)
93 fSum += pArray[i]; // Let errors encoded as NaNs propagate ???
95 else
96 fSum += pArray[i];
100 return fSum;
103 } // end namespace sc::op
105 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */