]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // sum_kahan.hpp | |
3 | // | |
4 | // Copyright 2010 Gaetano Mendola, 2011 Simon West. Distributed under the Boost | |
5 | // Software License, Version 1.0. (See accompanying file | |
6 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
7 | ||
8 | #ifndef BOOST_ACCUMULATORS_STATISTICS_SUM_KAHAN_HPP_EAN_26_07_2010 | |
9 | #define BOOST_ACCUMULATORS_STATISTICS_SUM_KAHAN_HPP_EAN_26_07_2010 | |
10 | ||
11 | #include <boost/accumulators/framework/accumulator_base.hpp> | |
12 | #include <boost/accumulators/framework/parameters/sample.hpp> | |
13 | #include <boost/accumulators/statistics_fwd.hpp> | |
14 | #include <boost/accumulators/statistics/sum.hpp> | |
15 | #include <boost/accumulators/statistics/weighted_sum_kahan.hpp> | |
16 | #include <boost/numeric/conversion/cast.hpp> | |
17 | ||
18 | namespace boost { namespace accumulators | |
19 | { | |
20 | ||
21 | namespace impl | |
22 | { | |
23 | ||
24 | #if _MSC_VER > 1400 | |
25 | # pragma float_control(push) | |
26 | # pragma float_control(precise, on) | |
27 | #endif | |
28 | ||
29 | template<typename Sample, typename Tag> | |
30 | struct sum_kahan_impl | |
31 | : accumulator_base | |
32 | { | |
33 | typedef Sample result_type; | |
34 | ||
35 | //////////////////////////////////////////////////////////////////////////// | |
36 | // sum_kahan_impl | |
37 | /** | |
38 | @brief Kahan summation algorithm | |
39 | ||
40 | The Kahan summation algorithm reduces the numerical error obtained with standard | |
41 | sequential sum. | |
42 | ||
43 | */ | |
44 | template<typename Args> | |
45 | sum_kahan_impl(Args const & args) | |
46 | : sum(args[parameter::keyword<Tag>::get() | Sample()]), | |
47 | compensation(boost::numeric_cast<Sample>(0.0)) | |
48 | { | |
49 | } | |
50 | ||
51 | template<typename Args> | |
52 | void | |
53 | #if BOOST_ACCUMULATORS_GCC_VERSION > 40305 | |
54 | __attribute__((__optimize__("no-associative-math"))) | |
55 | #endif | |
56 | operator ()(Args const & args) | |
57 | { | |
58 | const Sample myTmp1 = args[parameter::keyword<Tag>::get()] - this->compensation; | |
59 | const Sample myTmp2 = this->sum + myTmp1; | |
60 | this->compensation = (myTmp2 - this->sum) - myTmp1; | |
61 | this->sum = myTmp2; | |
62 | } | |
63 | ||
64 | result_type result(dont_care) const | |
65 | { | |
66 | return this->sum; | |
67 | } | |
68 | ||
69 | private: | |
70 | Sample sum; | |
71 | Sample compensation; | |
72 | }; | |
73 | ||
74 | #if _MSC_VER > 1400 | |
75 | # pragma float_control(pop) | |
76 | #endif | |
77 | ||
78 | } // namespace impl | |
79 | ||
80 | /////////////////////////////////////////////////////////////////////////////// | |
81 | // tag::sum_kahan | |
82 | // tag::sum_of_weights_kahan | |
83 | // tag::sum_of_variates_kahan | |
84 | // | |
85 | namespace tag | |
86 | { | |
87 | ||
88 | struct sum_kahan | |
89 | : depends_on<> | |
90 | { | |
91 | /// INTERNAL ONLY | |
92 | /// | |
93 | typedef impl::sum_kahan_impl< mpl::_1, tag::sample > impl; | |
94 | }; | |
95 | ||
96 | struct sum_of_weights_kahan | |
97 | : depends_on<> | |
98 | { | |
99 | typedef mpl::true_ is_weight_accumulator; | |
100 | /// INTERNAL ONLY | |
101 | /// | |
102 | typedef accumulators::impl::sum_kahan_impl<mpl::_2, tag::weight> impl; | |
103 | }; | |
104 | ||
105 | template<typename VariateType, typename VariateTag> | |
106 | struct sum_of_variates_kahan | |
107 | : depends_on<> | |
108 | { | |
109 | /// INTERNAL ONLY | |
110 | /// | |
111 | typedef mpl::always<accumulators::impl::sum_kahan_impl<VariateType, VariateTag> > impl; | |
112 | }; | |
113 | ||
114 | } // namespace tag | |
115 | ||
116 | /////////////////////////////////////////////////////////////////////////////// | |
117 | // extract::sum_kahan | |
118 | // extract::sum_of_weights_kahan | |
119 | // extract::sum_of_variates_kahan | |
120 | // | |
121 | namespace extract | |
122 | { | |
123 | extractor<tag::sum_kahan> const sum_kahan = {}; | |
124 | extractor<tag::sum_of_weights_kahan> const sum_of_weights_kahan = {}; | |
125 | extractor<tag::abstract_sum_of_variates> const sum_of_variates_kahan = {}; | |
126 | ||
127 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(sum_kahan) | |
128 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(sum_of_weights_kahan) | |
129 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(sum_of_variates_kahan) | |
130 | } // namespace extract | |
131 | ||
132 | using extract::sum_kahan; | |
133 | using extract::sum_of_weights_kahan; | |
134 | using extract::sum_of_variates_kahan; | |
135 | ||
136 | // sum(kahan) -> sum_kahan | |
137 | template<> | |
138 | struct as_feature<tag::sum(kahan)> | |
139 | { | |
140 | typedef tag::sum_kahan type; | |
141 | }; | |
142 | ||
143 | // sum_of_weights(kahan) -> sum_of_weights_kahan | |
144 | template<> | |
145 | struct as_feature<tag::sum_of_weights(kahan)> | |
146 | { | |
147 | typedef tag::sum_of_weights_kahan type; | |
148 | }; | |
149 | ||
150 | // So that sum_kahan can be automatically substituted with | |
151 | // weighted_sum_kahan when the weight parameter is non-void. | |
152 | template<> | |
153 | struct as_weighted_feature<tag::sum_kahan> | |
154 | { | |
155 | typedef tag::weighted_sum_kahan type; | |
156 | }; | |
157 | ||
158 | template<> | |
159 | struct feature_of<tag::weighted_sum_kahan> | |
160 | : feature_of<tag::sum> | |
161 | {}; | |
162 | ||
163 | // for the purposes of feature-based dependency resolution, | |
164 | // sum_kahan provides the same feature as sum | |
165 | template<> | |
166 | struct feature_of<tag::sum_kahan> | |
167 | : feature_of<tag::sum> | |
168 | { | |
169 | }; | |
170 | ||
171 | // for the purposes of feature-based dependency resolution, | |
172 | // sum_of_weights_kahan provides the same feature as sum_of_weights | |
173 | template<> | |
174 | struct feature_of<tag::sum_of_weights_kahan> | |
175 | : feature_of<tag::sum_of_weights> | |
176 | { | |
177 | }; | |
178 | ||
179 | template<typename VariateType, typename VariateTag> | |
180 | struct feature_of<tag::sum_of_variates_kahan<VariateType, VariateTag> > | |
181 | : feature_of<tag::abstract_sum_of_variates> | |
182 | { | |
183 | }; | |
184 | ||
185 | }} // namespace boost::accumulators | |
186 | ||
187 | #endif | |
188 |