h_infsup.hpp 3.62 KB
Newer Older
Edwin Carlinet's avatar
Edwin Carlinet committed
1
#ifndef MLN_ACCU_ACCUMULATORS_H_INFSUP_HPP
Michaël Roynard's avatar
Michaël Roynard committed
2
#define MLN_ACCU_ACCUMULATORS_H_INFSUP_HPP
Edwin Carlinet's avatar
Edwin Carlinet committed
3

Michaël Roynard's avatar
Michaël Roynard committed
4
5
6
7
#include <mln/accu/accumulator_base.hpp>
#include <mln/accu/accumulators/infsup.hpp>
#include <mln/core/value/indexer.hpp>
#include <mln/core/value/value_traits.hpp>
Edwin Carlinet's avatar
Edwin Carlinet committed
8

Edwin Carlinet's avatar
Edwin Carlinet committed
9
#ifdef _MSC_VER
Michaël Roynard's avatar
Michaël Roynard committed
10
#pragma warning(disable : 4800)
Edwin Carlinet's avatar
Edwin Carlinet committed
11
12
#endif

Edwin Carlinet's avatar
Edwin Carlinet committed
13
14
15
16
17
18
19
20
21
22
23
/// FIXME: use indexer / rename has histogram

namespace mln
{

  namespace accu
  {

    namespace accumulators
    {
      /// \brief An accumulator that computes the infimum of values
Michaël Roynard's avatar
Michaël Roynard committed
24
      /// based on the tracking of values. It provides
Edwin Carlinet's avatar
Edwin Carlinet committed
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
      template <class T>
      struct h_inf;

      template <class T>
      struct h_sup;
    }

    namespace features
    {
      struct h_inf;
      struct h_sup;
    }

    /******************************************/
    /****          Implementation          ****/
    /******************************************/

    namespace features
    {

      struct h_inf : simple_feature_facade<h_inf, accumulators::h_inf>
      {
      };

      struct h_sup : simple_feature_facade<h_sup, accumulators::h_sup>
      {
      };
    }

    namespace accumulators
    {

      template <typename E, typename T, typename F, typename Enable = void>
      struct h_infsup_base;

      template <typename E, typename T, typename F>
Michaël Roynard's avatar
Michaël Roynard committed
61
62
63
      struct h_infsup_base<E, T, F,
                           typename std::enable_if<std::is_integral<T>::value and value_traits<T>::quant <= 16>::type>
          : accumulator_base<E, T, T, F>
Edwin Carlinet's avatar
Edwin Carlinet committed
64
65
66
      {
        typedef T argument_type;
        typedef T result_type;
Michaël Roynard's avatar
Michaël Roynard committed
67
        typedef boost::mpl::set<features::h_sup, features::h_inf, features::inf<>, features::sup<>> provides;
Edwin Carlinet's avatar
Edwin Carlinet committed
68
69

        h_infsup_base()
Michaël Roynard's avatar
Michaël Roynard committed
70
71
72
            : m_inf(value_traits<T>::sup()), m_sup(value_traits<T>::inf()), m_count(0), m_hist{{
                                                                                            0,
                                                                                        }}
Edwin Carlinet's avatar
Edwin Carlinet committed
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
        {
        }

        void init()
        {
          m_inf = value_traits<T>::sup();
          m_sup = value_traits<T>::inf();
          m_count = 0;
          m_hist.fill(0);
        }

        void take(const T& x)
        {
          ++m_hist[x];
          ++m_count;
Michaël Roynard's avatar
Michaël Roynard committed
88
89
90
91
          if (x < m_inf)
            m_inf = x;
          if (x > m_sup)
            m_sup = x;
Edwin Carlinet's avatar
Edwin Carlinet committed
92
93
94
95
        }

        void untake(const T& x)
        {
96
          mln_precondition(m_count > 0);
Edwin Carlinet's avatar
Edwin Carlinet committed
97
98
99
100
101
          mln_precondition(m_hist[x] > 0);
          --m_hist[x];
          --m_count;

          if (m_hist[x] == 0)
Michaël Roynard's avatar
Michaël Roynard committed
102
103
104
105
106
107
108
109
110
111
112
113
114
115
          {
            if (m_count == 0)
            {
              m_inf = value_traits<T>::sup();
              m_sup = value_traits<T>::inf();
            }
            else if (x == m_inf)
            {
              int i = m_inf;
              while (not m_hist[i])
                ++i;
              m_inf = i;
            }
            else if (x == m_sup)
Edwin Carlinet's avatar
Edwin Carlinet committed
116
            {
Michaël Roynard's avatar
Michaël Roynard committed
117
118
119
120
              int i = m_sup;
              while (not m_hist[i])
                --i;
              m_sup = i;
Edwin Carlinet's avatar
Edwin Carlinet committed
121
            }
Michaël Roynard's avatar
Michaël Roynard committed
122
          }
Edwin Carlinet's avatar
Edwin Carlinet committed
123
124
        }

Michaël Roynard's avatar
Michaël Roynard committed
125
        friend T extract(const h_infsup_base& accu, features::inf<>) { return accu.m_inf; }
Edwin Carlinet's avatar
Edwin Carlinet committed
126

Michaël Roynard's avatar
Michaël Roynard committed
127
        friend T extract(const h_infsup_base& accu, features::sup<>) { return accu.m_sup; }
Edwin Carlinet's avatar
Edwin Carlinet committed
128
129
130
131
132
133
134
135
136

      protected:
        T m_inf;
        T m_sup;
        unsigned m_count;
        std::array<unsigned, indexer<T, std::less<T>>::nvalues> m_hist;
      };

      template <typename T>
Michaël Roynard's avatar
Michaël Roynard committed
137
      struct h_inf : h_infsup_base<h_inf<T>, T, features::inf<>>
Edwin Carlinet's avatar
Edwin Carlinet committed
138
139
140
141
      {
      };

      template <typename T>
Michaël Roynard's avatar
Michaël Roynard committed
142
      struct h_sup : h_infsup_base<h_sup<T>, T, features::sup<>>
Edwin Carlinet's avatar
Edwin Carlinet committed
143
144
145
146
147
148
      {
      };
    }
  }
}

Michaël Roynard's avatar
Michaël Roynard committed
149
#endif //! MLN_ACCU_ACCUMULATORS_H_INFSUP_HPP