summaryrefslogtreecommitdiff
path: root/boost/math/tools/univariate_statistics.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/math/tools/univariate_statistics.hpp')
-rw-r--r--boost/math/tools/univariate_statistics.hpp43
1 files changed, 39 insertions, 4 deletions
diff --git a/boost/math/tools/univariate_statistics.hpp b/boost/math/tools/univariate_statistics.hpp
index 226fdf46d2..387ff859ee 100644
--- a/boost/math/tools/univariate_statistics.hpp
+++ b/boost/math/tools/univariate_statistics.hpp
@@ -30,12 +30,47 @@ auto mean(ForwardIterator first, ForwardIterator last)
}
return mu;
}
- else
+ else if constexpr (std::is_same_v<typename std::iterator_traits<ForwardIterator>::iterator_category, std::random_access_iterator_tag>)
{
- Real mu = 0;
+ size_t elements = std::distance(first, last);
+ Real mu0 = 0;
+ Real mu1 = 0;
+ Real mu2 = 0;
+ Real mu3 = 0;
Real i = 1;
- for(auto it = first; it != last; ++it) {
- mu = mu + (*it - mu)/i;
+ auto end = last - (elements % 4);
+ for(auto it = first; it != end; it += 4) {
+ Real inv = Real(1)/i;
+ Real tmp0 = (*it - mu0);
+ Real tmp1 = (*(it+1) - mu1);
+ Real tmp2 = (*(it+2) - mu2);
+ Real tmp3 = (*(it+3) - mu3);
+ // please generate a vectorized fma here
+ mu0 += tmp0*inv;
+ mu1 += tmp1*inv;
+ mu2 += tmp2*inv;
+ mu3 += tmp3*inv;
+ i += 1;
+ }
+ Real num1 = Real(elements - (elements %4))/Real(4);
+ Real num2 = num1 + Real(elements % 4);
+
+ for (auto it = end; it != last; ++it)
+ {
+ mu3 += (*it-mu3)/i;
+ i += 1;
+ }
+
+ return (num1*(mu0+mu1+mu2) + num2*mu3)/Real(elements);
+ }
+ else
+ {
+ auto it = first;
+ Real mu = *it;
+ Real i = 2;
+ while(++it != last)
+ {
+ mu += (*it - mu)/i;
i += 1;
}
return mu;