Commit d75e6fa4 authored by Edwin Carlinet's avatar Edwin Carlinet
Browse files

Fix accumulator issue with dynamic parameter in meta accumulators.

Fix affects also the Kernel Library that uses aggregators.
parent b35b7008
...@@ -5,26 +5,71 @@ ...@@ -5,26 +5,71 @@
# include <mln/accu/feature.hpp> # include <mln/accu/feature.hpp>
# include <mln/accu/composite_accumulator.hpp> # include <mln/accu/composite_accumulator.hpp>
/// \defgroup accu Accumulator framework
/// \{
/// \file
/// \brief Header file for the accumulator framework
namespace mln namespace mln
{ {
namespace accu namespace accu
{ {
/// \brief The namespace for accumulator features.
namespace features namespace features
{ {
} }
/// \brief The namespace for accumulator object themselves.
namespace accumulators namespace accumulators
{ {
} }
/// \brief The namespace for feature extractor.
namespace extractor namespace extractor
{ {
} }
/// \defgroup freefun Free functions # ifdef MLN_DOXYGEN
/// \{ /// \brief Make a concrete accumulator from an accumulator-like object \p accu.
/// If \p accu is a feature-set, it is bound to the argument type of \p arg, otherwise
/// \tparam A the accumulator-like type.
/// \tparam T the value type to accumulate
/// \param accu the accumulator-like object
/// \param arg a value prototype to accumulate
///
/// \code
/// accu::features::max<> myfeat;
/// auto myaccu = accu::make_accumulator(myfeat, int());
/// myaccu.init();
/// myaccu.take(15); myaccu.take(5);
/// int m = myaccu.to_result() // 15
/// \endcode
///
template <typename A, typename T>
unspecified make_accumulator(const AccumulatorLike<A>& accu, T arg);
/// \brief Helper structure to get the return type of an accumulator-like object.
/// It defines an internal member type named \p type which is the result type
/// of the accumulator
/// \tparam AccuLike The type of the accumulator-like object.
/// \tparam T The argument type (the type of values to accumulate)
/// \tparam Extractor The function used to extract the result from the accumulator
template <typename AccuLike, typename T, typename Extractor = default_extractor>
struct result_of
{
typedef unspecified type;
};
/// \brief The defaut extractor
/// It calls the `to_result` method of the accumulator.
struct default_extractor;
# endif
# ifndef MLN_DOXYGEN
template <typename A, typename ...> template <typename A, typename ...>
A& make_accumulator(Accumulator<A>& accu); A& make_accumulator(Accumulator<A>& accu);
...@@ -34,46 +79,46 @@ namespace mln ...@@ -34,46 +79,46 @@ namespace mln
template <typename F, typename T> template <typename F, typename T>
typename F::template apply<T>::type typename F::template apply<T>::type
make_accumulator(const FeatureSet<F>& feat, T = T()); make_accumulator(const FeatureSet<F>& feat, T = T());
/// \}
struct default_extractor struct default_extractor
{ {
template <typename A>
template <typename A> typename A::result_type
typename A::result_type operator() (const Accumulator<A>& accu) const
operator() (const Accumulator<A>& accu) const {
{
return exact(accu).to_result(); return exact(accu).to_result();
} }
}; };
# endif
template <typename AccuLike, typename T, typename Extractor = default_extractor, template <typename AccuLike, typename T, typename Extractor = default_extractor,
typename Enabler = void> typename Enabler = void>
struct result_of struct result_of
{ {
static_assert( std::is_convertible<AccuLike, FeatureSet<AccuLike> >::value, static_assert( std::is_convertible<AccuLike, FeatureSet<AccuLike> >::value,
"sdfsd"); "sdfsd");
}; };
template <typename AccuLike, typename T, typename Extractor> template <typename AccuLike, typename T, typename Extractor>
struct result_of<AccuLike, T, Extractor, struct result_of<AccuLike, T, Extractor,
typename std::enable_if< is_a<AccuLike, FeatureSet>::value >::type> typename std::enable_if< is_a<AccuLike, FeatureSet>::value >::type>
{ {
private: private:
typedef typename AccuLike::template apply<T>::type Accu; typedef typename AccuLike::template apply<T>::type Accu;
public: public:
typedef typename std::result_of<Extractor(Accu)>::type type; typedef typename std::result_of<Extractor(Accu)>::type type;
}; };
template <typename AccuLike, typename T, typename Extractor> template <typename AccuLike, typename T, typename Extractor>
struct result_of<AccuLike, T, Extractor, struct result_of<AccuLike, T, Extractor,
typename std::enable_if< is_a<AccuLike, Accumulator>::value >::type> typename std::enable_if< is_a<AccuLike, Accumulator>::value >::type>
{ {
typedef typename std::result_of<Extractor(AccuLike)>::type type; typedef typename std::result_of<Extractor(AccuLike)>::type type;
}; };
...@@ -88,8 +133,8 @@ namespace mln ...@@ -88,8 +133,8 @@ namespace mln
template <typename A, typename ...> template <typename A, typename ...>
A& make_accumulator(Accumulator<A>& accu) A& make_accumulator(Accumulator<A>& accu)
{ {
return exact(accu); return exact(accu);
} }
template <typename A, typename ...> template <typename A, typename ...>
const A& make_accumulator(const Accumulator<A>& accu, ...) const A& make_accumulator(const Accumulator<A>& accu, ...)
...@@ -99,13 +144,15 @@ namespace mln ...@@ -99,13 +144,15 @@ namespace mln
template <typename F, typename T> template <typename F, typename T>
typename F::template apply<T>::type typename F::template apply<T>::type
make_accumulator(const FeatureSet<F>&, T) make_accumulator(const FeatureSet<F>& fs, T)
{ {
return typename F::template apply<T>::type (); return exact(fs).template make<T>();
} }
} }
} }
/// \}
#endif // ! ACCUMULATOR_HPP #endif // ! ACCUMULATOR_HPP
#ifndef MLN_ACCU_ACCUMULATOTS_COUNT_HPP #ifndef MLN_ACCU_ACCUMULATOTS_COUNT_HPP
# define MLN_ACCU_ACCUMULATOTS_COUNT_HPP # define MLN_ACCU_ACCUMULATOTS_COUNT_HPP
/// \file
/// \brief Header file for counting accumulator.
# include <mln/accu/accumulator_base.hpp> # include <mln/accu/accumulator_base.hpp>
# include <mln/accu/dontcare.hpp> # include <mln/accu/dontcare.hpp>
# include <utility> # include <utility>
...@@ -12,6 +15,9 @@ namespace mln ...@@ -12,6 +15,9 @@ namespace mln
{ {
namespace accumulators namespace accumulators
{ {
/// \brief The counting accumulator.
/// \tparam CountType is underlying the counter type (it must be incrementable,
/// and decrementable.
template <typename CountType = std::size_t> template <typename CountType = std::size_t>
struct count; struct count;
} }
...@@ -29,9 +35,9 @@ namespace mln ...@@ -29,9 +35,9 @@ namespace mln
inline inline
auto auto
count(const Accumulator<A>& acc) count(const Accumulator<A>& acc)
-> decltype(extract(exact(acc), features::count<> ())) -> decltype(extract(exact(acc), features::count<> ()))
{ {
return extract(exact(acc), features::count<> ()); return extract(exact(acc), features::count<> ());
} }
} }
...@@ -39,17 +45,22 @@ namespace mln ...@@ -39,17 +45,22 @@ namespace mln
namespace features namespace features
{ {
template <typename CountType> template <typename CountType>
struct count : simple_feature< count<CountType> > struct count : simple_feature< count<CountType> >
{ {
template <typename T> template <typename T>
struct apply struct apply
{ {
typedef accumulators::count<CountType> type; typedef accumulators::count<CountType> type;
}; };
template <typename T>
accumulators::count<CountType>
make()
{
return accumulators::count<CountType> ();
}
}; };
} }
namespace accumulators namespace accumulators
...@@ -58,44 +69,44 @@ namespace mln ...@@ -58,44 +69,44 @@ namespace mln
template <typename CountType> template <typename CountType>
struct count : accumulator_base< count<CountType>, dontcare, CountType, features::count<> > struct count : accumulator_base< count<CountType>, dontcare, CountType, features::count<> >
{ {
typedef dontcare argument_type; typedef dontcare argument_type;
typedef CountType return_type; typedef CountType result_type;
typedef boost::mpl::set< features::count<> > provides; typedef boost::mpl::set< features::count<> > provides;
count() count()
: m_count (0) : m_count (0)
{ {
} }
void init() void init()
{ {
m_count = 0; m_count = 0;
} }
void take(const dontcare&) void take(const dontcare&)
{ {
++m_count; ++m_count;
} }
void untake(const dontcare&) void untake(const dontcare&)
{ {
--m_count; --m_count;
} }
template <typename Other> template <typename Other>
void take(const Accumulator<Other>& other) void take(const Accumulator<Other>& other)
{ {
m_count += extractor::count(other); m_count += extractor::count(other);
} }
friend friend
return_type extract(const count& accu, features::count<> ) result_type extract(const count& accu, features::count<> )
{ {
return accu.m_count; return accu.m_count;
} }
private: private:
CountType m_count; CountType m_count;
}; };
} }
......
...@@ -11,11 +11,18 @@ namespace mln ...@@ -11,11 +11,18 @@ namespace mln
namespace accu namespace accu
{ {
namespace accumulators namespace accumulators
{ {
template <typename T, typename Compare = productorder_less<T> > template <typename T, typename Compare = productorder_less<T> >
struct infsup; struct infsup;
template <typename T, typename Compare = std::less<T> >
struct sup;
template <typename T, typename Compare = std::less<T> >
struct inf;
} }
namespace features namespace features
...@@ -33,17 +40,17 @@ namespace mln ...@@ -33,17 +40,17 @@ namespace mln
template <typename A> template <typename A>
auto auto
inf(const Accumulator<A>& acc) inf(const Accumulator<A>& acc)
-> decltype( extract(exact(acc), features::inf<> ()) ) -> decltype( extract(exact(acc), features::inf<> ()) )
{ {
return extract(exact(acc), features::inf<> ()); return extract(exact(acc), features::inf<> ());
} }
template <typename A> template <typename A>
auto auto
sup(const Accumulator<A>& acc) sup(const Accumulator<A>& acc)
-> decltype( extract(exact(acc), features::sup<> ()) ) -> decltype( extract(exact(acc), features::sup<> ()) )
{ {
return extract(exact(acc), features::sup<> ()); return extract(exact(acc), features::sup<> ());
} }
} }
...@@ -55,43 +62,93 @@ namespace mln ...@@ -55,43 +62,93 @@ namespace mln
template <typename Compare> template <typename Compare>
struct inf : simple_feature< inf<Compare> > struct inf : simple_feature< inf<Compare> >
{ {
template <typename T> inf(const Compare& cmp)
struct apply : m_cmp(cmp)
{ {
typedef accumulators::infsup<T, Compare> type; }
};
template <typename T>
struct apply
{
typedef accumulators::sup<T, Compare> type;
};
template <typename T>
accumulators::sup<T, Compare>
make() const
{
return accumulators::sup<T, Compare>(m_cmp);
}
private:
Compare m_cmp;
}; };
template <> template <>
struct inf<void> : simple_feature< inf<void> > struct inf<void> : simple_feature< inf<void> >
{ {
template <typename T> inf() = default;
struct apply
{ template <typename T>
typedef accumulators::infsup<T, std::less<T> > type; struct apply
}; {
typedef accumulators::sup<T> type;
};
template <typename T>
accumulators::sup<T>
make() const
{
return accumulators::sup<T>();
}
}; };
template <typename Compare> template <typename Compare>
struct sup : simple_feature< sup<Compare> > struct sup : simple_feature< sup<Compare> >
{ {
template <typename T> sup(const Compare& cmp)
struct apply : m_cmp(cmp)
{ {
typedef accumulators::infsup<T, Compare> type; }
};
template <typename T>
struct apply
{
typedef accumulators::sup<T, Compare> type;
};
template <typename T>
accumulators::sup<T, Compare>
make() const
{
return accumulators::sup<T, Compare>(m_cmp);
}
private:
Compare m_cmp;
}; };
template <> template <>
struct sup<void> : simple_feature< sup<void> > struct sup<void> : simple_feature< sup<void> >
{ {
template <typename T> sup() = default;
struct apply
{ template <typename T>
typedef accumulators::infsup<T, std::less<T> > type; struct apply
}; {
typedef accumulators::sup<T> type;
};
template <typename T>
accumulators::sup<T>
make() const
{
return accumulators::sup<T>();
}
}; };
} }
namespace accumulators namespace accumulators
...@@ -100,62 +157,162 @@ namespace mln ...@@ -100,62 +157,162 @@ namespace mln
template <typename T, typename Compare> template <typename T, typename Compare>
struct infsup : Accumulator< infsup<T, Compare> > struct infsup : Accumulator< infsup<T, Compare> >
{ {
typedef T argument_type; typedef T argument_type;
typedef std::pair<T,T> result_type; typedef std::pair<T,T> result_type;
typedef boost::mpl::set< typedef boost::mpl::set<
features::inf<>, features::sup<> > provides; features::inf<>, features::sup<> > provides;
infsup(const Compare& cmp = Compare()) infsup(const Compare& cmp = Compare())
: m_inf( value_traits<T, Compare>::sup() ), : m_inf( value_traits<T, Compare>::sup() ),
m_sup( value_traits<T, Compare>::inf() ), m_sup( value_traits<T, Compare>::inf() ),
m_cmp( cmp ) m_cmp( cmp )
{ {
} }
void init() void init()
{ {
m_inf = value_traits<T, Compare>::sup(); m_inf = value_traits<T, Compare>::sup();
m_sup = value_traits<T, Compare>::inf(); m_sup = value_traits<T, Compare>::inf();
} }
void take(const T& v) void take(const T& v)
{ {
m_inf = inf(m_inf, v, m_cmp); using mln::inf;
m_sup = sup(m_sup, v, m_cmp); using mln::sup;
} m_inf = inf(m_inf, v, m_cmp);
m_sup = sup(m_sup, v, m_cmp);
template <typename Other>