File indexing completed on 2025-01-18 09:28:22
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_QUANTILE_HPP_DE_01_01_2006
0009 #define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_QUANTILE_HPP_DE_01_01_2006
0010
0011 #include <cmath>
0012 #include <functional>
0013 #include <boost/array.hpp>
0014 #include <boost/parameter/keyword.hpp>
0015 #include <boost/mpl/placeholders.hpp>
0016 #include <boost/type_traits/is_same.hpp>
0017 #include <boost/accumulators/framework/accumulator_base.hpp>
0018 #include <boost/accumulators/framework/extractor.hpp>
0019 #include <boost/accumulators/numeric/functional.hpp>
0020 #include <boost/accumulators/framework/parameters/sample.hpp>
0021 #include <boost/accumulators/statistics_fwd.hpp>
0022 #include <boost/accumulators/statistics/count.hpp>
0023 #include <boost/accumulators/statistics/sum.hpp>
0024 #include <boost/accumulators/statistics/parameters/quantile_probability.hpp>
0025
0026 namespace boost { namespace accumulators
0027 {
0028
0029 namespace impl {
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 template<typename Sample, typename Weight, typename Impl>
0054 struct weighted_p_square_quantile_impl
0055 : accumulator_base
0056 {
0057 typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample;
0058 typedef typename numeric::functional::fdiv<weighted_sample, std::size_t>::result_type float_type;
0059 typedef array<float_type, 5> array_type;
0060
0061 typedef float_type result_type;
0062
0063 template<typename Args>
0064 weighted_p_square_quantile_impl(Args const &args)
0065 : p(is_same<Impl, for_median>::value ? 0.5 : args[quantile_probability | 0.5])
0066 , heights()
0067 , actual_positions()
0068 , desired_positions()
0069 {
0070 }
0071
0072 template<typename Args>
0073 void operator ()(Args const &args)
0074 {
0075 std::size_t cnt = count(args);
0076
0077
0078 if (cnt <= 5)
0079 {
0080 this->heights[cnt - 1] = args[sample];
0081
0082
0083
0084
0085 this->actual_positions[cnt - 1] = args[weight];
0086
0087
0088 if (cnt == 5)
0089 {
0090
0091
0092
0093 typename array_type::iterator it_begin, it_end, it_min;
0094
0095 it_begin = this->heights.begin();
0096 it_end = this->heights.end();
0097
0098 std::size_t pos = 0;
0099
0100 while (it_begin != it_end)
0101 {
0102 it_min = std::min_element(it_begin, it_end);
0103 std::size_t d = std::distance(it_begin, it_min);
0104 std::swap(*it_begin, *it_min);
0105 std::swap(this->actual_positions[pos], this->actual_positions[pos + d]);
0106 ++it_begin;
0107 ++pos;
0108 }
0109
0110
0111 for (std::size_t i = 1; i < 5; ++i)
0112 {
0113 this->actual_positions[i] += this->actual_positions[i - 1];
0114 }
0115 }
0116 }
0117 else
0118 {
0119 std::size_t sample_cell = 1;
0120
0121
0122 if (args[sample] < this->heights[0])
0123 {
0124 this->heights[0] = args[sample];
0125 this->actual_positions[0] = args[weight];
0126 sample_cell = 1;
0127 }
0128 else if (this->heights[4] <= args[sample])
0129 {
0130 this->heights[4] = args[sample];
0131 sample_cell = 4;
0132 }
0133 else
0134 {
0135 typedef typename array_type::iterator iterator;
0136 iterator it = std::upper_bound(
0137 this->heights.begin()
0138 , this->heights.end()
0139 , args[sample]
0140 );
0141
0142 sample_cell = std::distance(this->heights.begin(), it);
0143 }
0144
0145
0146 for (std::size_t i = sample_cell; i < 5; ++i)
0147 {
0148 this->actual_positions[i] += args[weight];
0149 }
0150
0151
0152 this->desired_positions[0] = this->actual_positions[0];
0153 this->desired_positions[1] = (sum_of_weights(args) - this->actual_positions[0])
0154 * this->p/2. + this->actual_positions[0];
0155 this->desired_positions[2] = (sum_of_weights(args) - this->actual_positions[0])
0156 * this->p + this->actual_positions[0];
0157 this->desired_positions[3] = (sum_of_weights(args) - this->actual_positions[0])
0158 * (1. + this->p)/2. + this->actual_positions[0];
0159 this->desired_positions[4] = sum_of_weights(args);
0160
0161
0162 for (std::size_t i = 1; i <= 3; ++i)
0163 {
0164
0165 float_type d = this->desired_positions[i] - this->actual_positions[i];
0166
0167
0168 float_type dp = this->actual_positions[i + 1] - this->actual_positions[i];
0169
0170
0171 float_type dm = this->actual_positions[i - 1] - this->actual_positions[i];
0172
0173
0174 float_type hp = (this->heights[i + 1] - this->heights[i]) / dp;
0175 float_type hm = (this->heights[i - 1] - this->heights[i]) / dm;
0176
0177 if ( ( d >= 1. && dp > 1. ) || ( d <= -1. && dm < -1. ) )
0178 {
0179 short sign_d = static_cast<short>(d / std::abs(d));
0180
0181
0182 float_type h = this->heights[i] + sign_d / (dp - dm) * ( (sign_d - dm) * hp + (dp - sign_d) * hm );
0183
0184 if ( this->heights[i - 1] < h && h < this->heights[i + 1] )
0185 {
0186 this->heights[i] = h;
0187 }
0188 else
0189 {
0190
0191 if (d>0)
0192 {
0193 this->heights[i] += hp;
0194 }
0195 if (d<0)
0196 {
0197 this->heights[i] -= hm;
0198 }
0199 }
0200 this->actual_positions[i] += sign_d;
0201 }
0202 }
0203 }
0204 }
0205
0206 result_type result(dont_care) const
0207 {
0208 return this->heights[2];
0209 }
0210
0211
0212
0213 template<class Archive>
0214 void serialize(Archive & ar, const unsigned int file_version)
0215 {
0216 ar & p;
0217 ar & heights;
0218 ar & actual_positions;
0219 ar & desired_positions;
0220 }
0221
0222 private:
0223 float_type p;
0224 array_type heights;
0225 array_type actual_positions;
0226 array_type desired_positions;
0227 };
0228
0229 }
0230
0231
0232
0233
0234 namespace tag
0235 {
0236 struct weighted_p_square_quantile
0237 : depends_on<count, sum_of_weights>
0238 {
0239 typedef accumulators::impl::weighted_p_square_quantile_impl<mpl::_1, mpl::_2, regular> impl;
0240 };
0241 struct weighted_p_square_quantile_for_median
0242 : depends_on<count, sum_of_weights>
0243 {
0244 typedef accumulators::impl::weighted_p_square_quantile_impl<mpl::_1, mpl::_2, for_median> impl;
0245 };
0246 }
0247
0248
0249
0250
0251
0252 namespace extract
0253 {
0254 extractor<tag::weighted_p_square_quantile> const weighted_p_square_quantile = {};
0255 extractor<tag::weighted_p_square_quantile_for_median> const weighted_p_square_quantile_for_median = {};
0256
0257 BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_p_square_quantile)
0258 BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_p_square_quantile_for_median)
0259 }
0260
0261 using extract::weighted_p_square_quantile;
0262 using extract::weighted_p_square_quantile_for_median;
0263
0264 }}
0265
0266 #endif