vSMC
vSMC: Scalable Monte Carlo
counter.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/utility/counter.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013,2014, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef VSMC_UTILITY_COUNTER_HPP
33 #define VSMC_UTILITY_COUNTER_HPP
34 
35 #include <vsmc/internal/common.hpp>
36 #include <vsmc/utility/array.hpp>
37 
38 namespace vsmc {
39 
40 namespace internal {
41 
42 template <typename T, bool> struct CounterMask;
43 
44 template <typename T>
45 struct CounterMask<T, true>
46 {
47  static VSMC_CONSTEXPR const T max_val =
48  static_cast<T>(~(static_cast<T>(0)));
49 
50  static VSMC_CONSTEXPR const T mask_hi =
51  static_cast<T>(static_cast<T>(max_val << 8) >> 8);
52 
53  static VSMC_CONSTEXPR const T mask_lo =
54  static_cast<T>(mask_hi^max_val);
55 }; // struct CounterMask
56 
57 } // namespace vsmc::internal
58 
59 template <typename> class Counter;
60 
88 template <typename T, std::size_t K>
89 class Counter<Array<T, K> >
90 {
91  public :
92 
94 
96  static inline void set (ctr_type &ctr, const ctr_type &c) {ctr = c;}
97 
99  template <std::size_t Blocks>
100  static inline void set (Array<ctr_type, Blocks> &ctr, const ctr_type &c)
101  {
102  ctr.front() = c;
103  set_block<1>(ctr, cxx11::integral_constant<bool, 1 < Blocks>());
104  }
105 
107  static inline void reset (ctr_type &ctr)
108  {std::memset(ctr.data(), 0, sizeof(T) * K);}
109 
111  template <std::size_t Blocks>
112  static inline void reset (Array<ctr_type, Blocks> &ctr)
113  {
114  reset(ctr.front());
115  set_block<1>(ctr, cxx11::integral_constant<bool, 1 < Blocks>());
116  }
117 
119  static inline void increment (ctr_type &ctr)
120  {increment_single<0>(ctr, cxx11::integral_constant<bool, 1 < K>());}
121 
123  template <std::size_t Blocks>
124  static inline void increment (Array<ctr_type, Blocks> &ctr)
125  {increment_block<0>(ctr, cxx11::true_type());}
126 
128  static inline void increment (ctr_type &ctr, T nskip)
129  {
130  if (nskip == 0)
131  return;
132 
133  if (K == 1) {
134  ctr.front() += nskip;
135  return;
136  }
137 
138  if (nskip == 1) {
139  increment(ctr);
140  return;
141  }
142 
143  if (ctr.front() <= max_ - nskip) {
144  ctr.front() += nskip;
145  return;
146  }
147 
148  nskip -= max_ - ctr.front();
149  ctr.front() = max_;
150  increment(ctr);
151  ctr.front() = nskip - 1;
152  }
153 
155  template <std::size_t Blocks>
156  static inline void increment (Array<ctr_type, Blocks> &ctr, T nskip)
157  {
158  if (nskip == 0)
159  return;
160 
161  if (nskip == 1) {
162  increment(ctr);
163  return;
164  }
165 
166  increment_block<0>(ctr, nskip, cxx11::true_type());
167  }
168 
169  private :
170 
171  static VSMC_CONSTEXPR const T max_ =
173 
174  static VSMC_CONSTEXPR const T mask_hi_ =
176 
177  static VSMC_CONSTEXPR const T mask_lo_ =
179 
180  template <std::size_t>
181  static inline void increment_single (ctr_type &ctr, cxx11::false_type)
182  {++ctr.back();}
183 
184  template <std::size_t N>
185  static inline void increment_single (ctr_type &ctr, cxx11::true_type)
186  {
187  if (++ctr[Position<N>()] != 0)
188  return;
189 
190  increment_single<N + 1>(ctr,
191  cxx11::integral_constant<bool, N + 2 < K>());
192  }
193 
194  template <std::size_t, std::size_t Blocks>
195  static inline void set_block (Array<ctr_type, Blocks> &,
197 
198  template <std::size_t B, std::size_t Blocks>
199  static inline void set_block (Array<ctr_type, Blocks> &ctr,
201  {
202  T m = ctr[Position<B - 1>()].back() & mask_lo_;
203  m >>= sizeof(T) * 8 - 8;
204  ++m;
205  m <<= sizeof(T) * 8 - 8;
206 
207  ctr[Position<B>()] = ctr[Position<B - 1>()];
208  ctr[Position<B>()].back() &= mask_hi_;
209  ctr[Position<B>()].back() ^= m;
210  set_block<B + 1>(ctr,
211  cxx11::integral_constant<bool, B + 1 < Blocks>());
212  }
213 
214  template <std::size_t, std::size_t Blocks>
215  static inline void increment_block (Array<ctr_type, Blocks> &,
217 
218  template <std::size_t B, std::size_t Blocks>
219  static inline void increment_block (Array<ctr_type, Blocks> &ctr,
221  {
222  increment_block_ctr(ctr[Position<B>()]);
223  increment_block<B + 1>(ctr,
224  cxx11::integral_constant<bool, B + 1 < Blocks>());
225  }
226 
227  template <std::size_t, std::size_t Blocks>
228  static inline void increment_block (Array<ctr_type, Blocks> &, T,
230 
231  template <std::size_t B, std::size_t Blocks>
232  static inline void increment_block (Array<ctr_type, Blocks> &ctr, T nskip,
234  {
235  increment_block_ctr(ctr[Position<B>()], nskip);
236  increment_block<B + 1>(ctr, nskip,
237  cxx11::integral_constant<bool, B + 1 < Blocks>());
238  }
239 
240  static inline void increment_block_ctr (ctr_type &ctr)
241  {increment_block_single<0>(ctr, cxx11::integral_constant<bool, 1 < K>());}
242 
243  static inline void increment_block_ctr (ctr_type &ctr, T nskip)
244  {
245  increment_block_nskip(ctr, nskip,
246  cxx11::integral_constant<bool, 1 < K>());
247  }
248 
249  template <std::size_t>
250  static inline void increment_block_single (ctr_type &ctr,
252  {
253  T m = ctr.back() & mask_lo_;
254  ctr.back() <<= 8;
255  ctr.back() >>= 8;
256  ++ctr.back();
257  ctr.back() &= mask_hi_;
258  ctr.back() ^= m;
259  }
260 
261  template <std::size_t N>
262  static inline void increment_block_single (ctr_type &ctr,
264  {
265  if (++ctr[Position<N>()] != 0)
266  return;
267 
268  increment_block_single<N + 1>(ctr,
269  cxx11::integral_constant<bool, N + 2 < K>());
270  }
271 
272  static inline void increment_block_nskip (ctr_type &ctr, T nskip,
274  {
275  T m = ctr.back() & mask_lo_;
276  T b = ctr.back();
277  b <<= 8;
278  b >>= 8;
279 
280  if (nskip <= mask_hi_ - b) {
281  b += nskip;
282  b &= mask_hi_;
283  b ^= m;
284  ctr.back() = b;
285  return;
286  }
287 
288  nskip -= mask_hi_ - b - 1;
289  while (nskip > mask_hi_)
290  nskip -= mask_hi_;
291  b = nskip;
292  b &= mask_hi_;
293  b ^= m;
294  ctr.back() = b;
295  }
296 
297  static inline void increment_block_nskip (ctr_type &ctr, T nskip,
299  {
300  if (nskip == 0)
301  return;
302 
303  if (nskip == 1) {
304  increment_block_ctr(ctr);
305  return;
306  }
307 
308  if (ctr.front() <= max_ - nskip) {
309  ctr.front() += nskip;
310  return;
311  }
312 
313  nskip -= max_ - ctr.front();
314  ctr.front() = max_;
315  increment_block_ctr(ctr);
316  ctr.front() = nskip - 1;
317  }
318 }; // struct Counter
319 
320 } // namespace vsmc
321 
322 #endif // VSMC_UTILITY_COUNTER_HPP
Definition: adapter.hpp:37
static void set(Array< ctr_type, Blocks > &ctr, const ctr_type &c)
Set a block of counters given the value of the first counter.
Definition: counter.hpp:100
static void reset(Array< ctr_type, Blocks > &ctr)
Reset a block of counters with the first set to zero.
Definition: counter.hpp:112
#define VSMC_CONSTEXPR
constexpr
Definition: defines.hpp:55
static void increment(Array< ctr_type, Blocks > &ctr)
Increment each counter in a block by one.
Definition: counter.hpp:124
reference front()
Definition: array.hpp:119
static void increment(ctr_type &ctr, T nskip)
Increment a counter by a given value.
Definition: counter.hpp:128
integral_constant< bool, false > false_type
void * memset(void *dst, int ch, std::size_t n)
SIMD optimized memset with non-temporal store for large buffers.
Definition: cstring.hpp:906
static void set(ctr_type &ctr, const ctr_type &c)
Set the counter to a given value.
Definition: counter.hpp:96
static void reset(ctr_type &ctr)
Reset a counter to zero.
Definition: counter.hpp:107
integral_constant< bool, true > true_type
pointer data()
Definition: array.hpp:127
static void increment(Array< ctr_type, Blocks > &ctr, T nskip)
Increment each counter in a block by a given value.
Definition: counter.hpp:156
Static array.
Definition: array.hpp:79
static void increment(ctr_type &ctr)
Increment the counter by one.
Definition: counter.hpp:119