annotate DEPENDENCIES/generic/include/boost/accumulators/statistics/tail.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 ///////////////////////////////////////////////////////////////////////////////
Chris@16 2 // tail.hpp
Chris@16 3 //
Chris@16 4 // Copyright 2005 Eric Niebler, Michael Gauckler. Distributed under the Boost
Chris@16 5 // Software License, Version 1.0. (See accompanying file
Chris@16 6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 7
Chris@16 8 #ifndef BOOST_ACCUMULATORS_STATISTICS_TAIL_HPP_EAN_28_10_2005
Chris@16 9 #define BOOST_ACCUMULATORS_STATISTICS_TAIL_HPP_EAN_28_10_2005
Chris@16 10
Chris@16 11 #include <vector>
Chris@16 12 #include <functional>
Chris@16 13 #include <boost/assert.hpp>
Chris@16 14 #include <boost/range.hpp>
Chris@16 15 #include <boost/mpl/if.hpp>
Chris@16 16 #include <boost/mpl/or.hpp>
Chris@16 17 #include <boost/mpl/placeholders.hpp>
Chris@16 18 #include <boost/parameter/keyword.hpp>
Chris@16 19 #include <boost/iterator/reverse_iterator.hpp>
Chris@16 20 #include <boost/iterator/permutation_iterator.hpp>
Chris@16 21 #include <boost/accumulators/accumulators_fwd.hpp>
Chris@16 22 #include <boost/accumulators/framework/accumulator_base.hpp>
Chris@16 23 #include <boost/accumulators/framework/extractor.hpp>
Chris@16 24 #include <boost/accumulators/numeric/functional.hpp>
Chris@16 25 #include <boost/accumulators/framework/parameters/sample.hpp>
Chris@16 26 #include <boost/accumulators/framework/depends_on.hpp>
Chris@16 27 #include <boost/accumulators/statistics_fwd.hpp>
Chris@16 28
Chris@16 29 namespace boost { namespace accumulators
Chris@16 30 {
Chris@16 31 ///////////////////////////////////////////////////////////////////////////////
Chris@16 32 // cache_size named parameters
Chris@16 33 BOOST_PARAMETER_NESTED_KEYWORD(tag, right_tail_cache_size, cache_size)
Chris@16 34 BOOST_PARAMETER_NESTED_KEYWORD(tag, left_tail_cache_size, cache_size)
Chris@16 35
Chris@16 36 BOOST_ACCUMULATORS_IGNORE_GLOBAL(right_tail_cache_size)
Chris@16 37 BOOST_ACCUMULATORS_IGNORE_GLOBAL(left_tail_cache_size)
Chris@16 38
Chris@16 39 namespace detail
Chris@16 40 {
Chris@16 41 ///////////////////////////////////////////////////////////////////////////////
Chris@16 42 // tail_range
Chris@16 43 /// INTERNAL ONLY
Chris@16 44 ///
Chris@16 45 template<typename ElementIterator, typename IndexIterator>
Chris@16 46 struct tail_range
Chris@16 47 {
Chris@16 48 typedef boost::iterator_range<
Chris@16 49 boost::reverse_iterator<boost::permutation_iterator<ElementIterator, IndexIterator> >
Chris@16 50 > type;
Chris@16 51 };
Chris@16 52
Chris@16 53 ///////////////////////////////////////////////////////////////////////////////
Chris@16 54 // make_tail_range
Chris@16 55 /// INTERNAL ONLY
Chris@16 56 ///
Chris@16 57 template<typename ElementIterator, typename IndexIterator>
Chris@16 58 typename tail_range<ElementIterator, IndexIterator>::type
Chris@16 59 make_tail_range(ElementIterator elem_begin, IndexIterator index_begin, IndexIterator index_end)
Chris@16 60 {
Chris@16 61 return boost::make_iterator_range(
Chris@16 62 boost::make_reverse_iterator(
Chris@16 63 boost::make_permutation_iterator(elem_begin, index_end)
Chris@16 64 )
Chris@16 65 , boost::make_reverse_iterator(
Chris@16 66 boost::make_permutation_iterator(elem_begin, index_begin)
Chris@16 67 )
Chris@16 68 );
Chris@16 69 }
Chris@16 70
Chris@16 71 ///////////////////////////////////////////////////////////////////////////////
Chris@16 72 // stat_assign_visitor
Chris@16 73 /// INTERNAL ONLY
Chris@16 74 ///
Chris@16 75 template<typename Args>
Chris@16 76 struct stat_assign_visitor
Chris@16 77 {
Chris@16 78 stat_assign_visitor(Args const &a, std::size_t i)
Chris@16 79 : args(a)
Chris@16 80 , index(i)
Chris@16 81 {
Chris@16 82 }
Chris@16 83
Chris@16 84 template<typename Stat>
Chris@16 85 void operator ()(Stat &stat) const
Chris@16 86 {
Chris@16 87 stat.assign(this->args, this->index);
Chris@16 88 }
Chris@16 89
Chris@16 90 private:
Chris@16 91 stat_assign_visitor &operator =(stat_assign_visitor const &);
Chris@16 92 Args const &args;
Chris@16 93 std::size_t index;
Chris@16 94 };
Chris@16 95
Chris@16 96 ///////////////////////////////////////////////////////////////////////////////
Chris@16 97 // stat_assign
Chris@16 98 /// INTERNAL ONLY
Chris@16 99 ///
Chris@16 100 template<typename Args>
Chris@16 101 inline stat_assign_visitor<Args> const stat_assign(Args const &args, std::size_t index)
Chris@16 102 {
Chris@16 103 return stat_assign_visitor<Args>(args, index);
Chris@16 104 }
Chris@16 105
Chris@16 106 ///////////////////////////////////////////////////////////////////////////////
Chris@16 107 // is_tail_variate_feature
Chris@16 108 /// INTERNAL ONLY
Chris@16 109 ///
Chris@16 110 template<typename Stat, typename LeftRight>
Chris@16 111 struct is_tail_variate_feature
Chris@16 112 : mpl::false_
Chris@16 113 {
Chris@16 114 };
Chris@16 115
Chris@16 116 /// INTERNAL ONLY
Chris@16 117 ///
Chris@16 118 template<typename VariateType, typename VariateTag, typename LeftRight>
Chris@16 119 struct is_tail_variate_feature<tag::tail_variate<VariateType, VariateTag, LeftRight>, LeftRight>
Chris@16 120 : mpl::true_
Chris@16 121 {
Chris@16 122 };
Chris@16 123
Chris@16 124 /// INTERNAL ONLY
Chris@16 125 ///
Chris@16 126 template<typename LeftRight>
Chris@16 127 struct is_tail_variate_feature<tag::tail_weights<LeftRight>, LeftRight>
Chris@16 128 : mpl::true_
Chris@16 129 {
Chris@16 130 };
Chris@16 131
Chris@16 132 } // namespace detail
Chris@16 133
Chris@16 134 namespace impl
Chris@16 135 {
Chris@16 136 ///////////////////////////////////////////////////////////////////////////////
Chris@16 137 // tail_impl
Chris@16 138 template<typename Sample, typename LeftRight>
Chris@16 139 struct tail_impl
Chris@16 140 : accumulator_base
Chris@16 141 {
Chris@16 142 // LeftRight must be either right or left
Chris@16 143 BOOST_MPL_ASSERT((
Chris@16 144 mpl::or_<is_same<LeftRight, right>, is_same<LeftRight, left> >
Chris@16 145 ));
Chris@16 146
Chris@16 147 typedef
Chris@16 148 typename mpl::if_<
Chris@16 149 is_same<LeftRight, right>
Chris@16 150 , numeric::functional::greater<Sample const, Sample const>
Chris@16 151 , numeric::functional::less<Sample const, Sample const>
Chris@16 152 >::type
Chris@16 153 predicate_type;
Chris@16 154
Chris@16 155 // for boost::result_of
Chris@16 156 typedef typename detail::tail_range<
Chris@16 157 typename std::vector<Sample>::const_iterator
Chris@16 158 , std::vector<std::size_t>::iterator
Chris@16 159 >::type result_type;
Chris@16 160
Chris@16 161 template<typename Args>
Chris@16 162 tail_impl(Args const &args)
Chris@16 163 : is_sorted(false)
Chris@16 164 , indices()
Chris@16 165 , samples(args[tag::tail<LeftRight>::cache_size], args[sample | Sample()])
Chris@16 166 {
Chris@16 167 this->indices.reserve(this->samples.size());
Chris@16 168 }
Chris@16 169
Chris@16 170 tail_impl(tail_impl const &that)
Chris@16 171 : is_sorted(that.is_sorted)
Chris@16 172 , indices(that.indices)
Chris@16 173 , samples(that.samples)
Chris@16 174 {
Chris@16 175 this->indices.reserve(this->samples.size());
Chris@16 176 }
Chris@16 177
Chris@16 178 // This just stores the heap and the samples.
Chris@16 179 // In operator()() below, if we are adding a new sample
Chris@16 180 // to the sample cache, we force all the
Chris@16 181 // tail_variates to update also. (It's not
Chris@16 182 // good enough to wait for the accumulator_set to do it
Chris@16 183 // for us because then information about whether a sample
Chris@16 184 // was stored and where is lost, and would need to be
Chris@16 185 // queried at runtime, which would be slow.) This is
Chris@16 186 // implemented as a filtered visitation over the stats,
Chris@16 187 // which we can access because args[accumulator] gives us
Chris@16 188 // all the stats.
Chris@16 189
Chris@16 190 template<typename Args>
Chris@16 191 void operator ()(Args const &args)
Chris@16 192 {
Chris@16 193 if(this->indices.size() < this->samples.size())
Chris@16 194 {
Chris@16 195 this->indices.push_back(this->indices.size());
Chris@16 196 this->assign(args, this->indices.back());
Chris@16 197 }
Chris@16 198 else if(predicate_type()(args[sample], this->samples[this->indices[0]]))
Chris@16 199 {
Chris@16 200 std::pop_heap(this->indices.begin(), this->indices.end(), indirect_cmp(this->samples));
Chris@16 201 this->assign(args, this->indices.back());
Chris@16 202 }
Chris@16 203 }
Chris@16 204
Chris@16 205 result_type result(dont_care) const
Chris@16 206 {
Chris@16 207 if(!this->is_sorted)
Chris@16 208 {
Chris@16 209 // Must use the same predicate here as in push_heap/pop_heap above.
Chris@16 210 std::sort_heap(this->indices.begin(), this->indices.end(), indirect_cmp(this->samples));
Chris@16 211 // sort_heap puts elements in reverse order. Calling std::reverse
Chris@16 212 // turns the sorted sequence back into a valid heap.
Chris@16 213 std::reverse(this->indices.begin(), this->indices.end());
Chris@16 214 this->is_sorted = true;
Chris@16 215 }
Chris@16 216
Chris@16 217 return detail::make_tail_range(
Chris@16 218 this->samples.begin()
Chris@16 219 , this->indices.begin()
Chris@16 220 , this->indices.end()
Chris@16 221 );
Chris@16 222 }
Chris@16 223
Chris@16 224 private:
Chris@16 225
Chris@16 226 struct is_tail_variate
Chris@16 227 {
Chris@16 228 template<typename T>
Chris@16 229 struct apply
Chris@16 230 : detail::is_tail_variate_feature<
Chris@16 231 typename detail::feature_tag<T>::type
Chris@16 232 , LeftRight
Chris@16 233 >
Chris@16 234 {};
Chris@16 235 };
Chris@16 236
Chris@16 237 template<typename Args>
Chris@16 238 void assign(Args const &args, std::size_t index)
Chris@16 239 {
Chris@16 240 BOOST_ASSERT(index < this->samples.size());
Chris@16 241 this->samples[index] = args[sample];
Chris@16 242 std::push_heap(this->indices.begin(), this->indices.end(), indirect_cmp(this->samples));
Chris@16 243 this->is_sorted = false;
Chris@16 244 // Tell the tail variates to store their values also
Chris@16 245 args[accumulator].template visit_if<is_tail_variate>(detail::stat_assign(args, index));
Chris@16 246 }
Chris@16 247
Chris@16 248 ///////////////////////////////////////////////////////////////////////////////
Chris@16 249 //
Chris@16 250 struct indirect_cmp
Chris@16 251 : std::binary_function<std::size_t, std::size_t, bool>
Chris@16 252 {
Chris@16 253 indirect_cmp(std::vector<Sample> const &s)
Chris@16 254 : samples(s)
Chris@16 255 {
Chris@16 256 }
Chris@16 257
Chris@16 258 bool operator ()(std::size_t left, std::size_t right) const
Chris@16 259 {
Chris@16 260 return predicate_type()(this->samples[left], this->samples[right]);
Chris@16 261 }
Chris@16 262
Chris@16 263 private:
Chris@16 264 indirect_cmp &operator =(indirect_cmp const &);
Chris@16 265 std::vector<Sample> const &samples;
Chris@16 266 };
Chris@16 267
Chris@16 268 mutable bool is_sorted;
Chris@16 269 mutable std::vector<std::size_t> indices;
Chris@16 270 std::vector<Sample> samples;
Chris@16 271 };
Chris@16 272
Chris@16 273 } // namespace impl
Chris@16 274
Chris@16 275 // TODO The templatized tag::tail below should inherit from the correct named parameter.
Chris@16 276 // The following lines provide a workaround, but there must be a better way of doing this.
Chris@16 277 template<typename T>
Chris@16 278 struct tail_cache_size_named_arg
Chris@16 279 {
Chris@16 280 };
Chris@16 281 template<>
Chris@16 282 struct tail_cache_size_named_arg<left>
Chris@16 283 : tag::left_tail_cache_size
Chris@16 284 {
Chris@16 285 };
Chris@16 286 template<>
Chris@16 287 struct tail_cache_size_named_arg<right>
Chris@16 288 : tag::right_tail_cache_size
Chris@16 289 {
Chris@16 290 };
Chris@16 291
Chris@16 292 ///////////////////////////////////////////////////////////////////////////////
Chris@16 293 // tag::tail<>
Chris@16 294 //
Chris@16 295 namespace tag
Chris@16 296 {
Chris@16 297 template<typename LeftRight>
Chris@16 298 struct tail
Chris@16 299 : depends_on<>
Chris@16 300 , tail_cache_size_named_arg<LeftRight>
Chris@16 301 {
Chris@16 302 /// INTERNAL ONLY
Chris@16 303 ///
Chris@16 304 typedef accumulators::impl::tail_impl<mpl::_1, LeftRight> impl;
Chris@16 305
Chris@16 306 #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
Chris@16 307 /// tag::tail<LeftRight>::cache_size named parameter
Chris@16 308 static boost::parameter::keyword<tail_cache_size_named_arg<LeftRight> > const cache_size;
Chris@16 309 #endif
Chris@16 310 };
Chris@16 311
Chris@16 312 struct abstract_tail
Chris@16 313 : depends_on<>
Chris@16 314 {
Chris@16 315 };
Chris@16 316 }
Chris@16 317
Chris@16 318 ///////////////////////////////////////////////////////////////////////////////
Chris@16 319 // extract::tail
Chris@16 320 //
Chris@16 321 namespace extract
Chris@16 322 {
Chris@16 323 extractor<tag::abstract_tail> const tail = {};
Chris@16 324
Chris@16 325 BOOST_ACCUMULATORS_IGNORE_GLOBAL(tail)
Chris@16 326 }
Chris@16 327
Chris@16 328 using extract::tail;
Chris@16 329
Chris@16 330 template<typename LeftRight>
Chris@16 331 struct feature_of<tag::tail<LeftRight> >
Chris@16 332 : feature_of<tag::abstract_tail>
Chris@16 333 {
Chris@16 334 };
Chris@16 335
Chris@16 336 }} // namespace boost::accumulators
Chris@16 337
Chris@16 338 #endif