1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
15 #include "arraysumfunctor.hxx"
16 #include <formula/errorcodes.hxx>
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))
30 KahanSum
executeSSE2(size_t& i
, size_t nSize
, const double* pCurrent
);
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)
51 for (; i
+ 3 < nUnrolledSize
; i
+= 4)
58 // We are using pairwise summation alongside Kahan
59 return (sum0
+ sum1
) + (sum2
+ sum3
);
65 * This function task is to choose the fastest method available to perform the sum.
70 static inline KahanSum
executeFast(size_t& i
, size_t nSize
, const double* pCurrent
)
73 return executeSSE2(i
, nSize
, pCurrent
);
75 return executeUnrolled(i
, nSize
, pCurrent
);
80 * Performs the sum of an array.
81 * Note that align 16 will speed up the process.
85 inline KahanSum
sumArray(const double* pArray
, size_t nSize
)
88 const double* pCurrent
= pArray
;
89 KahanSum fSum
= executeFast(i
, nSize
, pCurrent
);
91 // sum rest of the array
92 for (; i
< nSize
; ++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
)
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 ???
120 } // end namespace sc::op
122 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */