LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
CountersMap.h
Go to the documentation of this file.
1 
8 #ifndef COUNTERSMAP_H
9 #define COUNTERSMAP_H
10 
11 // interface include
12 #include <cstddef> // std::ptrdiff_t
13 #include <map>
14 #include <array>
15 #include <functional> // std::less<>
16 #include <memory> // std::allocator<>
17 #include <utility> // std::pair<>
18 #include <iterator> // std::bidirectional_iterator_tag
19 #include <type_traits> // std::make_unsigned
20 
21 
22 namespace lar {
23 
25  constexpr bool IsPowerOf2(unsigned long long int v)
26  { return v & 1? v == 1: IsPowerOf2(v >> 1); }
27 
29  constexpr int LowestSetBit(unsigned long long int v);
30 
31 
32  namespace details {
33 
35  template <typename COUNTER, std::size_t NCounters>
36  class CounterBlock: public std::array<COUNTER, NCounters> {
37  public:
38  using Counter_t = COUNTER;
39 
40  using Array_t = std::array<Counter_t, NCounters>;
41  using value_type = typename Array_t::value_type;
42 
45 
48  { Array_t::operator[](index) = value; }
49 
50  void fill(const value_type& value) { Array_t::fill(value); }
51  void fill(size_t begin, size_t n, const value_type& value)
52  {
53  std::fill
54  (Array_t::data() + begin, Array_t::data() + begin + n, value);
55  }
56 
57  }; // CounterBlock
58 
59  template <
60  typename KEY,
61  typename COUNTER,
62  size_t SIZE
63  >
65 
66  using Key_t = KEY;
67  using Counter_t = COUNTER;
68 
70  static constexpr size_t NCounters = SIZE;
71 
74 
76  using PlainBaseMap_t = std::map<Key_t, CounterBlock_t, std::less<Key_t>>;
77 
79  using DefaultAllocator_t = typename PlainBaseMap_t::allocator_type;
80 
82  template <typename Alloc>
83  using BaseMap_t
84  = std::map<Key_t, CounterBlock_t, std::less<Key_t>, Alloc>;
85 
87  using MapValue_t = typename PlainBaseMap_t::value_type;
88 
89  }; // struct CountersMapTraits
90 
91  } // namespace details
92 
93 
94 
130  template <
131  typename KEY,
132  typename COUNTER,
133  size_t SIZE,
134  typename ALLOC
136  unsigned int SUBCOUNTERS=1
137  >
138  class CountersMap {
139  static_assert(SUBCOUNTERS == 1, "subcounters not implemented yet");
140  static_assert(IsPowerOf2(SIZE),
141  "the size of the cluster of counters must be a power of 2");
142 
145 
146  public:
147  using Key_t = KEY;
148  using Counter_t = COUNTER;
149  using Allocator_t = ALLOC;
150 
153 
154 
156  static constexpr size_t NCounters = Traits_t::NCounters;
157 
159  static constexpr size_t NSubcounters = NCounters * SUBCOUNTERS;
160 
163 
164 
166 
168  using BaseMap_t = typename Traits_t::template BaseMap_t<
169  typename std::allocator_traits<Allocator_t>::template rebind_alloc
170  <typename Traits_t::MapValue_t>
171  >;
172 
173  /*
175  using const_iterator = double_fwd_const_iterator<
176  typename BaseMap_t::const_iterator,
177  PairSecond<typename BaseMap_t::value_type>
178  >;
179  */
180 
185  // TODO others are missing
187 
188  using value_type = std::pair<const Key_t, SubCounter_t>;
189 
191  class const_iterator;
192 
193 
196 
199 
200 
202  SubCounter_t operator[] (Key_t key) const { return GetSubCounter(key); }
203 
216 
222  SubCounter_t increment(Key_t key);
223 
229  SubCounter_t decrement(Key_t key);
230 
231 
234  // this stuff needs serious work to be completed
235 
237  const_iterator begin() const;
238 
240  const_iterator end() const;
242 
243 
245  bool empty() const { return counter_map.empty(); }
246 
247 
249  typename std::make_unsigned<Key_t>::type n_counters() const
250  { return counter_map.size() * NSubcounters; }
251 
252 
270  template <typename OALLOC>
271  bool is_equal(
272  const std::map<Key_t, SubCounter_t, std::less<Key_t>, OALLOC>& to,
273  Key_t& first_difference
274  ) const;
275 
276 
282  template <typename OALLOC>
283  bool is_equal
284  (const std::map<Key_t, SubCounter_t, std::less<Key_t>, OALLOC>& to) const
285  { Key_t dummy; return is_equal(to, dummy); }
286 
287 
288  protected:
289 
290  using BlockKey_t = Key_t;
291  using CounterIndex_t = typename std::make_unsigned<Key_t>::type;
293 
294 
296  struct CounterKey_t {
299  // there should be a subcluster index here too
300 
301  CounterKey_t(): block(0), counter(0) {}
302 
305  block(major), counter(minor) {}
306 
309  // CounterKey_t(key >> MinorKeyBits, key & MinorKeyMask) {}
310  CounterKey_t(key & ~MinorKeyMask, key & MinorKeyMask) {}
311 
313  // Key_t Key() const { return (block << MinorKeyBits) + counter; }
314  Key_t Key() const { return block + counter; }
315 
317  operator Key_t() const { return Key(); }
318 
319 
321  { if (++counter == MinorKeyRange) next_block(); return *this; }
323  {
324  if (counter-- == 0) { prev_block(); counter = MinorKeyRange - 1; }
325  return *this;
326  } // operator--()
328  { CounterKey_t old(*this); this->operator++(); return old; }
330  { CounterKey_t old(*this); this->operator--(); return old; }
331 
333  CounterKey_t& start_block() { counter = 0; return *this; }
334 
337  { block -= MinorKeyRange; return start_block(); }
338 
341  { block += MinorKeyRange; return start_block(); }
342 
343 
345  static constexpr Key_t MinorKeyRange = NSubcounters;
346 
348  static constexpr Key_t MinorKeyBits = LowestSetBit(MinorKeyRange);
349 
351  static constexpr Key_t MinorKeyMask = MinorKeyRange - 1;
352 
353  static_assert
354  (MinorKeyBits > 0, "Wrong COUNTER value for lar::CountersMap");
355 
356  }; // struct CounterKey_t
357 
358 
360 
361 
363  Counter_t GetCounter(CounterKey_t key) const;
364 
366  // Since subcounters are not implemented yet, this is a no-op
368  { return GetCounter(key); }
369 
371  Counter_t& GetOrCreateCounter(CounterKey_t key);
372 
373 
375  static CounterKey_t SplitKey(Key_t key) { return key; }
376 
378  static const_iterator make_const_iterator
379  (typename BaseMap_t::const_iterator it, size_t ix)
380  { return { it, ix }; }
381 
382  private:
383 
385  SubCounter_t unchecked_set(CounterKey_t key, SubCounter_t delta);
386 
388  SubCounter_t unchecked_add(CounterKey_t key, SubCounter_t delta);
389 
390  }; // class CountersMap
391 
392 
393 } // namespace lar
394 
395 
396 //------------------------------------------------------------------------------
397 
398 namespace lar {
399 
400  namespace details {
402  inline constexpr int LowestSetBitScaler(unsigned long long int v, int b)
403  { return (v & 1)? b: LowestSetBitScaler(v >> 1, b + 1); }
404 
405  namespace counters_map {
406  static constexpr bool bDebug = true;
407 
408 
409  } // namespace counters_map
410  } // namespace details
411 
412 
413  inline constexpr int LowestSetBit(unsigned long long int v)
414  { return (v == 0)? -1: details::LowestSetBitScaler(v, 0); }
415 
416  // providing "definitions" of the static constants;
417  // these are required if the code is going to take the address of these
418  // constants, which is most often due to the use of "const size_t&" in some
419  // function, where "size_t" is a template argument type
420  // (or else the reference would not be needed).
421  // I am not providing the same for the protected and private members
422  // (just because of laziness).
423  template <typename K, typename C, size_t S, typename A, unsigned int SUB>
425 
426  template <typename K, typename C, size_t S, typename A, unsigned int SUB>
428 
429 
430  // CountersMap<>::const_iterator does not fully implement the STL iterator
431  // interface, since it does not implement operator-> () (for technical reason:
432  // the value does not actually exist and it does not have an address),
433  // in addition to std::swap().
434  template <typename K, typename C, size_t S, typename A, unsigned int SUB>
435  class CountersMap<K, C, S, A, SUB>::const_iterator:
436  public std::bidirectional_iterator_tag
437  {
439 
440  public:
442  using difference_type = std::ptrdiff_t;
443  using pointer = const value_type*;
444  using reference = const value_type&;
445  using iterator_category = std::bidirectional_iterator_tag;
446 
448 
450  const_iterator() = default;
451 
453  value_type operator*() const { return { key(), iter->second[index] }; }
454 
456  {
457  if (++index >= NSubcounters) { ++iter; index = 0; }
458  return *this;
459  } // operator++
461  { iterator_type old(*this); this->operator++(); return old; }
462 
464  {
465  if (index == 0) { --iter; index = NSubcounters - 1; }
466  else --index;
467  return *this;
468  } // operator--()
470  { iterator_type old(*this); this->operator--(); return old; }
471 
472  bool operator== (const iterator_type& as) const
473  { return (iter == as.iter) && (index == as.index); }
474  bool operator!= (const iterator_type& as) const
475  { return (iter != as.iter) || (index != as.index); }
476 
477 
479  CounterKey_t key() const { return { iter->first, index }; }
480 
481  protected:
485 
487  const_iterator(typename BaseMap_t::const_iterator it, size_t ix):
488  iter(it), index(ix) {}
489 
490  }; // CountersMap<>::const_iterator
491 
492 
493  template <typename K, typename C, size_t S, typename A, unsigned int SUB>
496  { return unchecked_set(CounterKey_t(key), value); }
497 
498  template <typename K, typename C, size_t S, typename A, unsigned int SUB>
501  { return unchecked_add(CounterKey_t(key), +1); }
502 
503  template <typename K, typename C, size_t S, typename A, unsigned int SUB>
506  { return unchecked_add(CounterKey_t(key), -1); }
507 
508 
509  template <typename K, typename C, size_t S, typename A, unsigned int SUB>
512  { return const_iterator{ counter_map.begin(), 0 }; }
513 
514  template <typename K, typename C, size_t S, typename A, unsigned int SUB>
517  { return const_iterator{ counter_map.end(), 0 }; }
518 
519 
520  template <typename K, typename C, size_t S, typename A, unsigned int SUB>
521  template <typename OALLOC>
523  const std::map<Key_t, SubCounter_t, std::less<Key_t>, OALLOC>& to,
524  Key_t& first_difference
525  ) const {
526  // this function is not optimised
527  using CompMap_t
528  = const std::map<Key_t, SubCounter_t, std::less<Key_t>, OALLOC>;
529  typename CompMap_t::const_iterator to_iter = to.begin(), to_end = to.end();
530  for (const typename const_iterator::value_type& p: *this) {
531 
532  if (to_iter != to_end) { // we have still counters to find
533  // if counter is already beyond the next non-empty one froml STL map,
534  // then we are missing some
535  if (p.first > to_iter->first) {
536  first_difference = to_iter->first;
537  return false;
538  }
539  // while (p.first > to_iter->first) {
540  // ++nMissingKeys;
541  // std::cout << "ERROR missing key " << to_iter->first << std::endl;
542  // if (++to_iter == to_end) break;
543  // } // while
544  // } // if
545  //
546  // if (to_iter != to_end) { // we have still counters to find
547  if (p.first == to_iter->first) {
548  // if the counter is in SLT map, the two counts must match
549  // std::cout << " " << p.first << " " << p.second << std::endl;
550  if (to_iter->second != p.second) {
551  // std::cout << "ERROR wrong counter value " << p.second
552  // << ", expected " << to_iter->second << std::endl;
553  // ++nMismatchValue;
554  first_difference = to_iter->first;
555  return false;
556  }
557  ++to_iter; // done with it
558  }
559  else if (p.first < to_iter->first) {
560  // if the counter is not in STL map, then it must be 0
561  if (p.second != 0) {
562  // ++nExtraKeys;
563  // std::cout << "ERROR extra key " << p.first << " (" << p.second << ")"
564  // << std::endl;
565  first_difference = p.first;
566  return false;
567  }
568  // else {
569  // std::cout << " " << p.first << " " << p.second << " (not in STL)"
570  // << std::endl;
571  // }
572  }
573  }
574  else { // if we are at the end of compared map
575  // no more keys in STL map
576  if (p.second != 0) {
577  // ++nExtraKeys;
578  // std::cout << "ERROR extra key " << p.first << " (" << p.second << ")"
579  // << std::endl;
580  first_difference = p.first;
581  return false;
582  }
583  }
584  } // for element in map
585 
586  return true;
587  } // CountersMap<>::is_equal()
588 
589 
590  template <typename K, typename C, size_t S, typename A, unsigned int SUB>
593  {
594  typename BaseMap_t::const_iterator iBlock = counter_map.find(key.block);
595  return (iBlock == counter_map.end())? 0: iBlock->second[key.counter];
596  } // CountersMap<>::GetCounter() const
597 
598 
599  template <typename K, typename C, size_t S, typename A, unsigned int SUB>
602  { return counter_map[key.block][key.counter]; }
603 
604 
605  template <typename K, typename C, size_t S, typename A, unsigned int SUB>
609  {
610  // take it low level here
611  // first get the iterator to the block
612  typename BaseMap_t::iterator iBlock = counter_map.lower_bound(key.block);
613  if (iBlock != counter_map.end()) {
614  if (iBlock->first == key.block) { // sweet, we have that counter already
615  return iBlock->second[key.counter] = value;
616  }
617  }
618  // no counter there yet: create one;
619  // hint to insert before the block in the position we jave already found
620  // (this is optimal in STL map for C++11);
621  // create a block using the special constructor;
622  // the temporary value created here is moved to the map
623  counter_map.insert(iBlock, { key.block, { key.counter, value } } );
624  return value;
625  } // CountersMap<>::unchecked_add() const
626 
627 
628  template <typename K, typename C, size_t S, typename A, unsigned int SUB>
632  {
633  // take it low level here
634  // first get the iterator to the block
635  typename BaseMap_t::iterator iBlock = counter_map.lower_bound(key.block);
636  if (iBlock != counter_map.end()) {
637  if (iBlock->first == key.block) { // sweet, we have that counter already
638  return iBlock->second[key.counter] += delta;
639  }
640  }
641  // no counter there yet: create one;
642  // hint to insert before the block in the position we jave already found
643  // (this is optimal in STL map for C++11);
644  // create a block using the special constructor;
645  // the temporary value created here is moved to the map
646  counter_map.insert(iBlock, { key.block, { key.counter, delta } } );
647  return delta;
648  } // CountersMap<>::unchecked_add() const
649 
650 
651 } // namespace lar
652 
653 
654 #endif // BULKALLOCATOR_H
CounterKey_t & operator--(int)
Definition: CountersMap.h:329
Key_t Key() const
Returns the full key.
Definition: CountersMap.h:314
Type of block of counters (just a STL array until SUBCOUNTERS are in)
Definition: CountersMap.h:36
const_iterator end() const
Returns an iterator past-the-end of the counters.
Definition: CountersMap.h:516
CounterKey_t & operator++(int)
Definition: CountersMap.h:327
typename Traits_t::CounterBlock_t CounterBlock_t
Definition: CountersMap.h:165
std::make_unsigned< Key_t >::type n_counters() const
Returns the number of allocated counters.
Definition: CountersMap.h:249
void fill(const value_type &value)
Definition: CountersMap.h:50
CountersMap(Allocator_t alloc)
Constructor, specifies an allocator.
Definition: CountersMap.h:198
static constexpr bool bDebug
Definition: CountersMap.h:406
CounterIndex_t counter
index of the counter in the block
Definition: CountersMap.h:298
intermediate_table::iterator iterator
KEY Key_t
type of counter key in the map
Definition: CountersMap.h:147
typename std::make_unsigned< Key_t >::type CounterIndex_t
type of index in the block
Definition: CountersMap.h:292
value_type operator*() const
Access to the pointed pair.
Definition: CountersMap.h:453
SubCounter_t increment(Key_t key)
Increments by 1 the specified counter.
Definition: CountersMap.h:500
Allocator_t allocator_type
type of the single counter
Definition: CountersMap.h:184
bool is_equal(const std::map< Key_t, SubCounter_t, std::less< Key_t >, OALLOC > &to, Key_t &first_difference) const
Returns whether the counters in this map are equivalent to another.
Definition: CountersMap.h:522
CounterIndex_t index
index of the counted in the subblock
Definition: CountersMap.h:484
typename CounterMap_t::value_type value_type
value type: pair
Definition: CountersMap.h:441
typename Array_t::value_type value_type
Definition: CountersMap.h:41
typename PlainBaseMap_t::value_type MapValue_t
Type of value in the map.
Definition: CountersMap.h:87
static CounterKey_t SplitKey(Key_t key)
Returns a split key corresponding to the specified key.
Definition: CountersMap.h:375
std::bidirectional_iterator_tag iterator_category
Definition: CountersMap.h:445
BaseMap_t::const_iterator iter
iterator to the block of counters
Definition: CountersMap.h:482
void fill(size_t begin, size_t n, const value_type &value)
Definition: CountersMap.h:51
Double_t K
CounterKey_t & next_block()
Skips to the beginning of the next block.
Definition: CountersMap.h:340
COUNTER Counter_t
Type of the single counter.
Definition: CountersMap.h:67
BlockKey_t block
key of the counter block
Definition: CountersMap.h:297
typename PlainBaseMap_t::allocator_type DefaultAllocator_t
Type of allocator for the plain map.
Definition: CountersMap.h:79
typename Traits_t::template BaseMap_t< typename std::allocator_traits< Allocator_t >::template rebind_alloc< typename Traits_t::MapValue_t > > BaseMap_t
Type of the map used in the implementation.
Definition: CountersMap.h:171
auto array(Array const &a)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:228
intermediate_table::const_iterator const_iterator
Key_t BlockKey_t
type of block key
Definition: CountersMap.h:290
CountersMap()
Default constructor (empty map)
Definition: CountersMap.h:195
iterator_type operator--(int)
Definition: CountersMap.h:469
Counter_t & GetOrCreateCounter(CounterKey_t key)
Returns the counter at the specified split key.
Definition: CountersMap.h:601
constexpr int LowestSetBitScaler(unsigned long long int v, int b)
Internally used by LowestSetBit.
Definition: CountersMap.h:402
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
SubCounter_t GetSubCounter(CounterKey_t key) const
Returns the value of the subcounter at the specified split key.
Definition: CountersMap.h:367
CounterKey_t(BlockKey_t major, CounterIndex_t minor)
Constructor from a pair.
Definition: CountersMap.h:304
CounterBlock()
Default constructor: initializes the array to 0.
Definition: CountersMap.h:44
CounterKey_t & start_block()
Skips to the beginning of this block.
Definition: CountersMap.h:333
COUNTER Counter_t
type of the single counter
Definition: CountersMap.h:148
CounterKey_t(Key_t key)
Initialize from a mangled key.
Definition: CountersMap.h:308
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
Counter_t GetCounter(CounterKey_t key) const
Returns the value of the counter at the specified split key.
Definition: CountersMap.h:592
const_iterator begin() const
Returns an iterator to the begin of the counters.
Definition: CountersMap.h:511
std::map< Key_t, CounterBlock_t, std::less< Key_t >, Alloc > BaseMap_t
Base type of map, allowing a custom allocator.
Definition: CountersMap.h:84
SubCounter_t decrement(Key_t key)
Decrements by 1 the specified counter.
Definition: CountersMap.h:505
const value_type & reference
Definition: CountersMap.h:444
std::array< Counter_t, NCounters > Array_t
type of base class
Definition: CountersMap.h:40
BaseMap_t counter_map
the actual data structure for counters
Definition: CountersMap.h:359
const_iterator(typename BaseMap_t::const_iterator it, size_t ix)
Private constructor (from a map iterator and a block index)
Definition: CountersMap.h:487
ALLOC Allocator_t
type of the single counter
Definition: CountersMap.h:149
Structure with the index of the counter, split as needed.
Definition: CountersMap.h:296
bool operator!=(geometry_element_iterator< GEOIDITER > const &iter, GEOIDITER const &id_iter)
Comparison operator: geometry ID and element point to different IDs.
SubCounter_t unchecked_set(CounterKey_t key, SubCounter_t delta)
Sets the specified counter to a value (no check on value range)
Definition: CountersMap.h:608
SubCounter_t mapped_type
type of the single counter
Definition: CountersMap.h:183
std::string value(boost::any const &)
LArSoft-specific namespace.
iterator_type operator++(int)
Definition: CountersMap.h:460
CounterKey_t key() const
Returns the key of the pointed item as a CounterKey_t.
Definition: CountersMap.h:479
std::map< Key_t, CounterBlock_t, std::less< Key_t >> PlainBaseMap_t
General type of map (no special allocator specified).
Definition: CountersMap.h:76
CounterBlock(size_t index, Counter_t value)
Convenience constructor: initializes all counters to 0, except one.
Definition: CountersMap.h:47
KEY Key_t
Type of counter key in the map.
Definition: CountersMap.h:66
Char_t n[5]
Map storing counters in a compact way.
Definition: CountersMap.h:138
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool empty() const
Returns whether the map has no counters.
Definition: CountersMap.h:245
SubCounter_t unchecked_add(CounterKey_t key, SubCounter_t delta)
Adds a delta to the specified counter (no check on underflow/overflow)
Definition: CountersMap.h:631
Counter_t SubCounter_t
Type of the subcounter (that is, the actual counter)
Definition: CountersMap.h:162
constexpr int LowestSetBit(unsigned long long int v)
Returns the position of the first set bit (0 for LSB)
Definition: CountersMap.h:413
SubCounter_t set(Key_t key, SubCounter_t value)
Sets the specified counter to a count.
Definition: CountersMap.h:495
CounterKey_t & prev_block()
Skips to the beginning of the previous block.
Definition: CountersMap.h:336
bool operator==(geometry_element_iterator< GEOIDITER > const &iter, GEOIDITER const &id_iter)
Comparison operator: geometry ID and element point to the same ID.
std::pair< const Key_t, SubCounter_t > value_type
Definition: CountersMap.h:188
constexpr bool IsPowerOf2(unsigned long long int v)
Returns true if the argument is a power of 2.
Definition: CountersMap.h:25