diff DEPENDENCIES/generic/include/boost/accumulators/statistics/tail.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DEPENDENCIES/generic/include/boost/accumulators/statistics/tail.hpp	Tue Aug 05 11:11:38 2014 +0100
@@ -0,0 +1,338 @@
+///////////////////////////////////////////////////////////////////////////////
+// tail.hpp
+//
+//  Copyright 2005 Eric Niebler, Michael Gauckler. Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_ACCUMULATORS_STATISTICS_TAIL_HPP_EAN_28_10_2005
+#define BOOST_ACCUMULATORS_STATISTICS_TAIL_HPP_EAN_28_10_2005
+
+#include <vector>
+#include <functional>
+#include <boost/assert.hpp>
+#include <boost/range.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <boost/parameter/keyword.hpp>
+#include <boost/iterator/reverse_iterator.hpp>
+#include <boost/iterator/permutation_iterator.hpp>
+#include <boost/accumulators/accumulators_fwd.hpp>
+#include <boost/accumulators/framework/accumulator_base.hpp>
+#include <boost/accumulators/framework/extractor.hpp>
+#include <boost/accumulators/numeric/functional.hpp>
+#include <boost/accumulators/framework/parameters/sample.hpp>
+#include <boost/accumulators/framework/depends_on.hpp>
+#include <boost/accumulators/statistics_fwd.hpp>
+
+namespace boost { namespace accumulators
+{
+///////////////////////////////////////////////////////////////////////////////
+// cache_size named parameters
+BOOST_PARAMETER_NESTED_KEYWORD(tag, right_tail_cache_size, cache_size)
+BOOST_PARAMETER_NESTED_KEYWORD(tag, left_tail_cache_size, cache_size)
+
+BOOST_ACCUMULATORS_IGNORE_GLOBAL(right_tail_cache_size)
+BOOST_ACCUMULATORS_IGNORE_GLOBAL(left_tail_cache_size)
+
+namespace detail
+{
+    ///////////////////////////////////////////////////////////////////////////////
+    // tail_range
+    /// INTERNAL ONLY
+    ///
+    template<typename ElementIterator, typename IndexIterator>
+    struct tail_range
+    {
+        typedef boost::iterator_range<
+            boost::reverse_iterator<boost::permutation_iterator<ElementIterator, IndexIterator> >
+        > type;
+    };
+
+    ///////////////////////////////////////////////////////////////////////////////
+    // make_tail_range
+    /// INTERNAL ONLY
+    ///
+    template<typename ElementIterator, typename IndexIterator>
+    typename tail_range<ElementIterator, IndexIterator>::type
+    make_tail_range(ElementIterator elem_begin, IndexIterator index_begin, IndexIterator index_end)
+    {
+        return boost::make_iterator_range(
+            boost::make_reverse_iterator(
+                boost::make_permutation_iterator(elem_begin, index_end)
+            )
+          , boost::make_reverse_iterator(
+                boost::make_permutation_iterator(elem_begin, index_begin)
+            )
+        );
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////
+    // stat_assign_visitor
+    /// INTERNAL ONLY
+    ///
+    template<typename Args>
+    struct stat_assign_visitor
+    {
+        stat_assign_visitor(Args const &a, std::size_t i)
+          : args(a)
+          , index(i)
+        {
+        }
+
+        template<typename Stat>
+        void operator ()(Stat &stat) const
+        {
+            stat.assign(this->args, this->index);
+        }
+
+    private:
+        stat_assign_visitor &operator =(stat_assign_visitor const &);
+        Args const &args;
+        std::size_t index;
+    };
+
+    ///////////////////////////////////////////////////////////////////////////////
+    // stat_assign
+    /// INTERNAL ONLY
+    ///
+    template<typename Args>
+    inline stat_assign_visitor<Args> const stat_assign(Args const &args, std::size_t index)
+    {
+        return stat_assign_visitor<Args>(args, index);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////
+    // is_tail_variate_feature
+    /// INTERNAL ONLY
+    ///
+    template<typename Stat, typename LeftRight>
+    struct is_tail_variate_feature
+      : mpl::false_
+    {
+    };
+
+    /// INTERNAL ONLY
+    ///
+    template<typename VariateType, typename VariateTag, typename LeftRight>
+    struct is_tail_variate_feature<tag::tail_variate<VariateType, VariateTag, LeftRight>, LeftRight>
+      : mpl::true_
+    {
+    };
+
+    /// INTERNAL ONLY
+    ///
+    template<typename LeftRight>
+    struct is_tail_variate_feature<tag::tail_weights<LeftRight>, LeftRight>
+      : mpl::true_
+    {
+    };
+
+} // namespace detail
+
+namespace impl
+{
+    ///////////////////////////////////////////////////////////////////////////////
+    // tail_impl
+    template<typename Sample, typename LeftRight>
+    struct tail_impl
+      : accumulator_base
+    {
+        // LeftRight must be either right or left
+        BOOST_MPL_ASSERT((
+            mpl::or_<is_same<LeftRight, right>, is_same<LeftRight, left> >
+        ));
+
+        typedef
+            typename mpl::if_<
+                is_same<LeftRight, right>
+              , numeric::functional::greater<Sample const, Sample const>
+              , numeric::functional::less<Sample const, Sample const>
+            >::type
+        predicate_type;
+
+        // for boost::result_of
+        typedef typename detail::tail_range<
+            typename std::vector<Sample>::const_iterator
+          , std::vector<std::size_t>::iterator
+        >::type result_type;
+
+        template<typename Args>
+        tail_impl(Args const &args)
+          : is_sorted(false)
+          , indices()
+          , samples(args[tag::tail<LeftRight>::cache_size], args[sample | Sample()])
+        {
+            this->indices.reserve(this->samples.size());
+        }
+
+        tail_impl(tail_impl const &that)
+          : is_sorted(that.is_sorted)
+          , indices(that.indices)
+          , samples(that.samples)
+        {
+            this->indices.reserve(this->samples.size());
+        }
+
+        // This just stores the heap and the samples.
+        // In operator()() below, if we are adding a new sample
+        // to the sample cache, we force all the
+        // tail_variates to update also. (It's not
+        // good enough to wait for the accumulator_set to do it
+        // for us because then information about whether a sample
+        // was stored and where is lost, and would need to be
+        // queried at runtime, which would be slow.) This is
+        // implemented as a filtered visitation over the stats,
+        // which we can access because args[accumulator] gives us
+        // all the stats.
+
+        template<typename Args>
+        void operator ()(Args const &args)
+        {
+            if(this->indices.size() < this->samples.size())
+            {
+                this->indices.push_back(this->indices.size());
+                this->assign(args, this->indices.back());
+            }
+            else if(predicate_type()(args[sample], this->samples[this->indices[0]]))
+            {
+                std::pop_heap(this->indices.begin(), this->indices.end(), indirect_cmp(this->samples));
+                this->assign(args, this->indices.back());
+            }
+        }
+
+        result_type result(dont_care) const
+        {
+            if(!this->is_sorted)
+            {
+                // Must use the same predicate here as in push_heap/pop_heap above.
+                std::sort_heap(this->indices.begin(), this->indices.end(), indirect_cmp(this->samples));
+                // sort_heap puts elements in reverse order. Calling std::reverse
+                // turns the sorted sequence back into a valid heap.
+                std::reverse(this->indices.begin(), this->indices.end());
+                this->is_sorted = true;
+            }
+
+            return detail::make_tail_range(
+                this->samples.begin()
+              , this->indices.begin()
+              , this->indices.end()
+            );
+        }
+
+    private:
+
+        struct is_tail_variate
+        {
+            template<typename T>
+            struct apply
+              : detail::is_tail_variate_feature<
+                    typename detail::feature_tag<T>::type
+                  , LeftRight
+                >
+            {};
+        };
+
+        template<typename Args>
+        void assign(Args const &args, std::size_t index)
+        {
+            BOOST_ASSERT(index < this->samples.size());
+            this->samples[index] = args[sample];
+            std::push_heap(this->indices.begin(), this->indices.end(), indirect_cmp(this->samples));
+            this->is_sorted = false;
+            // Tell the tail variates to store their values also
+            args[accumulator].template visit_if<is_tail_variate>(detail::stat_assign(args, index));
+        }
+
+        ///////////////////////////////////////////////////////////////////////////////
+        //
+        struct indirect_cmp
+          : std::binary_function<std::size_t, std::size_t, bool>
+        {
+            indirect_cmp(std::vector<Sample> const &s)
+              : samples(s)
+            {
+            }
+
+            bool operator ()(std::size_t left, std::size_t right) const
+            {
+                return predicate_type()(this->samples[left], this->samples[right]);
+            }
+
+        private:
+            indirect_cmp &operator =(indirect_cmp const &);
+            std::vector<Sample> const &samples;
+        };
+
+        mutable bool is_sorted;
+        mutable std::vector<std::size_t> indices;
+        std::vector<Sample> samples;
+    };
+
+} // namespace impl
+
+// TODO The templatized tag::tail below should inherit from the correct named parameter.
+// The following lines provide a workaround, but there must be a better way of doing this.
+template<typename T>
+struct tail_cache_size_named_arg
+{
+};
+template<>
+struct tail_cache_size_named_arg<left>
+  : tag::left_tail_cache_size
+{
+};
+template<>
+struct tail_cache_size_named_arg<right>
+  : tag::right_tail_cache_size
+{
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// tag::tail<>
+//
+namespace tag
+{
+    template<typename LeftRight>
+    struct tail
+      : depends_on<>
+      , tail_cache_size_named_arg<LeftRight>
+    {
+        /// INTERNAL ONLY
+        ///
+        typedef accumulators::impl::tail_impl<mpl::_1, LeftRight> impl;
+
+        #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
+        /// tag::tail<LeftRight>::cache_size named parameter
+        static boost::parameter::keyword<tail_cache_size_named_arg<LeftRight> > const cache_size;
+        #endif
+    };
+
+    struct abstract_tail
+      : depends_on<>
+    {
+    };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// extract::tail
+//
+namespace extract
+{
+    extractor<tag::abstract_tail> const tail = {};
+
+    BOOST_ACCUMULATORS_IGNORE_GLOBAL(tail)
+}
+
+using extract::tail;
+
+template<typename LeftRight>
+struct feature_of<tag::tail<LeftRight> >
+  : feature_of<tag::abstract_tail>
+{
+};
+
+}} // namespace boost::accumulators
+
+#endif