LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sc / inc / arraysumfunctor.hxx
blobc261c120addf3dd3abf098bb4e87c56a1b915551
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 "arraysumfunctor.hxx"
16 #include <formula/errorcodes.hxx>
18 namespace sc::op
20 // Checkout available optimization options.
21 // Note that it turned out to be problematic to support CPU-specific code
22 // that's not guaranteed to be available on that specific platform (see
23 // git history). SSE2 is guaranteed on x86_64 and it is our baseline requirement
24 // for x86 on Windows, so SSE2 use is hardcoded on those platforms.
25 // Whenever we raise baseline to e.g. AVX, this may get
26 // replaced with AVX code (get it from git history).
27 // Do it similarly with other platforms.
28 #if defined(X86_64) || (defined(X86) && defined(_WIN32))
29 #define SC_USE_SSE2 1
30 KahanSum executeSSE2(size_t& i, size_t nSize, const double* pCurrent);
31 #else
32 #define SC_USE_SSE2 0
33 #endif
35 /**
36 * If no boosts available, Unrolled KahanSum.
37 * Most likely to use on android.
39 static inline KahanSum executeUnrolled(size_t& i, size_t nSize, const double* pCurrent)
41 size_t nRealSize = nSize - i;
42 size_t nUnrolledSize = nRealSize - (nRealSize % 4);
44 if (nUnrolledSize > 0)
46 KahanSum sum0 = 0.0;
47 KahanSum sum1 = 0.0;
48 KahanSum sum2 = 0.0;
49 KahanSum sum3 = 0.0;
51 for (; i + 3 < nUnrolledSize; i += 4)
53 sum0 += *pCurrent++;
54 sum1 += *pCurrent++;
55 sum2 += *pCurrent++;
56 sum3 += *pCurrent++;
58 // We are using pairwise summation alongside Kahan
59 return (sum0 + sum1) + (sum2 + sum3);
61 return 0.0;
64 /**
65 * This function task is to choose the fastest method available to perform the sum.
66 * @param i
67 * @param nSize
68 * @param pCurrent
70 static inline KahanSum executeFast(size_t& i, size_t nSize, const double* pCurrent)
72 #if SC_USE_SSE2
73 return executeSSE2(i, nSize, pCurrent);
74 #else
75 return executeUnrolled(i, nSize, pCurrent);
76 #endif
79 /**
80 * Performs the sum of an array.
81 * Note that align 16 will speed up the process.
82 * @param pArray
83 * @param nSize
85 inline KahanSum sumArray(const double* pArray, size_t nSize)
87 size_t i = 0;
88 const double* pCurrent = pArray;
89 KahanSum fSum = executeFast(i, nSize, pCurrent);
91 // sum rest of the array
92 for (; i < nSize; ++i)
93 fSum += pArray[i];
95 // If the sum is a NaN, some of the terms were empty cells, probably.
96 // Re-calculate, carefully
97 double fVal = fSum.get();
98 if (!std::isfinite(fVal))
100 FormulaError nErr = GetDoubleErrorValue(fVal);
101 if (nErr == FormulaError::NoValue)
103 fSum = 0;
104 for (i = 0; i < nSize; i++)
106 if (!std::isfinite(pArray[i]))
108 nErr = GetDoubleErrorValue(pArray[i]);
109 if (nErr != FormulaError::NoValue)
110 fSum += pArray[i]; // Let errors encoded as NaNs propagate ???
112 else
113 fSum += pArray[i];
117 return fSum;
120 } // end namespace sc::op
122 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */