CMS 3D CMS Logo

DetSetVector.h
Go to the documentation of this file.
1 #ifndef DataFormats_Common_DetSetVector_h
2 #define DataFormats_Common_DetSetVector_h
3 
4 /*----------------------------------------------------------------------
5 
6 DetSetVector: A collection of homogeneous objects that can be used for
7 an EDProduct. DetSetVector is *not* designed for use as a base class
8 (it has no virtual functions).
9 
10 DetSetVector<T> contains a vector<DetSet<T> >, sorted on DetId, and
11 provides fast (O(log n)) lookups, but only O(n) insertion.
12 
13 It provides an interface such that EdmRef2 can directly reference, and
14 provide access to, individual T objects.
15 
16 The collection appears to the user as if it were a sequence of
17 DetSet<T>; e.g., operator[] returns a DetSet<T>&. However, the
18 argument to operator[] specifies the (DetId) identifier of the vector
19 to be returned, *not* the ordinal number of the T to be returned.
20 
21  ------------------
22  It is critical that users DO NOT MODIFY the id data member of a
23  DetSet object in a DetSetVector.
24  ------------------
25 
26 Since CMSSW 2_0_0_pre4, it is possible to skip the automatic sorting
27 when creating a DetSetVector<T> from an already sorted vector<DetSet<T>>.
28 If the DSV is not modified afterwards, it will no longer be sorted when
29 it is inserted in the event.
30 ONE NOTE OF CAUTION: it is not sufficient to to say that the vector is
31 sorted already. In addition the sorting must have been done with the same
32 criteria and obey the rules of "strict weak ordering" as will be used to
33 find things in the collection. Not insuring this leads to undefined
34 behavior (usually a core dump).
35 
36 ----------------------------------------------------------------------*/
37 
38 #include <algorithm>
39 #include <iterator>
40 #include <vector>
41 
42 #include <type_traits>
43 #include "boost/concept_check.hpp"
44 
50 
52 
54 
55 namespace edm {
56  class ProductID;
57 
58  //------------------------------------------------------------
59  // Forward declarations
60  template <class T>
61  class DetSetVector;
62 
63  //------------------------------------------------------------
64  // Helper function, to regularize throwing of exceptions.
65  //------------------------------------------------------------
66 
67  namespace detail {
68  // Throw an edm::Exception with an appropriate message
69  inline void _throw_range(det_id_type i) {
71  errors::InvalidReference, "DetSetVector::operator[] called with index not in collection;\nindex value: ", i);
72  }
73  } // namespace detail
74 
75  //------------------------------------------------------------
76  //
77 
78  // If DetSetVector<T> is instantiated with a class T which inherits
79  // from DoNotSortUponInsertion, the resulting class inherits from
80  // DoNotSortUponInsertion. In the normal case, DetSetVector<T>
81  // inherits from Other. (This is necessary to assure that
82  // DetSetVector<T> is not sorted upon insertion into the Event when
83  // T is defined to inherit from DoNotSortUponInsertion).
84 
85  template <class T>
86  class DetSetVector : public std::conditional_t<std::is_base_of<edm::DoNotSortUponInsertion, T>::value,
87  edm::DoNotSortUponInsertion,
88  Other> {
91  BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);
92 
93  public:
94  typedef DetSet<T> detset;
95  typedef detset value_type;
96  typedef std::vector<detset> collection_type;
97 
98  typedef detset& reference;
99  typedef detset const& const_reference;
100 
101  typedef typename collection_type::iterator iterator;
102  typedef typename collection_type::const_iterator const_iterator;
104 
107 
109  DetSetVector();
110 
122  explicit DetSetVector(std::vector<DetSet<T> >& input, bool alreadySorted = false);
123 
124  void swap(DetSetVector& other);
125 
127 
129  // What should happen if there is already a DetSet with this
130  // DetId? Right now, it is up to the user *not* to do this. If you
131  // are unsure whether or not your DetId is already in the
132  // DetSetVector, then use 'find_or_insert(id)' instead.
133  void insert(detset const& s);
134 
139 
141  bool empty() const;
142 
144  size_type size() const;
145 
146  // reserve...
147  void reserve(size_t s) { _sets.reserve(s); }
148 
149  // Do we need a short-hand method to return the number of T
150  // instances? If so, do we optimize for size (calculate on the
151  // fly) or speed (keep a current cache)?
152 
156  const_iterator find(det_id_type id) const;
157 
163 
165  iterator begin();
166  const_iterator begin() const;
167 
169  iterator end();
170  const_iterator end() const;
171 
174  void getIds(std::vector<det_id_type>& result) const;
175 
178  void post_insert();
179 
180  void fillView(ProductID const& id, std::vector<void const*>& pointers, FillViewHelperVector& helpers) const;
181 
182  //Used by ROOT storage
184 
185  private:
188 
190  void _sort();
191  };
192 
193  template <class T>
194  inline DetSetVector<T>::DetSetVector() : _sets() {}
195 
196  template <class T>
198  : _sets(), _alreadySorted(alreadySorted) {
199  _sets.swap(input);
200  if (!alreadySorted)
201  _sort();
202  }
203 
204  template <class T>
206  _sets.swap(other._sets);
207  bool tmp = _alreadySorted;
208  _alreadySorted = other._alreadySorted;
209  other._alreadySorted = tmp;
210  }
211 
212  template <class T>
213  inline DetSetVector<T>& DetSetVector<T>::operator=(DetSetVector<T> const& other) {
214  DetSetVector<T> temp(other);
215  swap(temp);
216  return *this;
217  }
218 
219  template <class T>
220  inline void DetSetVector<T>::insert(detset const& t) {
221  _alreadySorted = false; // we don't know if the DetSet we're adding is already sorted
222  // Implementation provided by the Performance Task Force.
223  _sets.insert(std::lower_bound(_sets.begin(), _sets.end(), t), t);
224 #if 0
225  // It seems we have to sort on each insertion, because we may
226  // perform lookups during construction.
227  _sets.push_back(t);
228 
229  _sort();
230 #endif
231  }
232 
233  template <class T>
235  // NOTE: we don't have to clear _alreadySorted: the new DS is empty,
236  // and gets inserted in the correct place
237  std::pair<iterator, iterator> p = std::equal_range(_sets.begin(), _sets.end(), id);
238 
239  // If the range isn't empty, we already have the right thing;
240  // return a reference to it...
241  if (p.first != p.second)
242  return *p.first;
243 
244  // Insert the right thing, in the right place, and return a
245  // reference to the newly inserted thing.
246 #if defined(__GXX_EXPERIMENTAL_CXX0X__)
247  return *(_sets.emplace(p.first, id));
248 #else
249  return *(_sets.insert(p.first, detset(id)));
250 #endif
251  }
252 
253  template <class T>
254  inline bool DetSetVector<T>::empty() const {
255  return _sets.empty();
256  }
257 
258  template <class T>
260  return _sets.size();
261  }
262 
263  template <class T>
265  _alreadySorted = false; // it's non const
266  std::pair<iterator, iterator> p = std::equal_range(_sets.begin(), _sets.end(), id);
267  if (p.first == p.second)
268  return _sets.end();
269 
270 // The range indicated by [p.first, p.second) should be exactly of
271 // length 1. It seems likely we don't want to take the time hit of
272 // checking this, but here is the appropriate test... We can turn
273 // it on if we need the debugging aid.
274 #if 0
275  assert(std::distance(p.first, p.second) == 1);
276 #endif
277 
278  return p.first;
279  }
280 
281  template <class T>
283  std::pair<const_iterator, const_iterator> p = std::equal_range(_sets.begin(), _sets.end(), id);
284  if (p.first == p.second)
285  return _sets.end();
286  // The range indicated by [p.first, p.second) should be exactly of
287  // length 1.
288  assert(std::distance(p.first, p.second) == 1);
289  return p.first;
290  }
291 
292  template <class T>
294  _alreadySorted = false; // it's non const
295  // Find the right DetSet, and return a reference to it. Throw if
296  // there is none.
297  iterator it = this->find(i);
298  if (it == this->end())
300  return *it;
301  }
302 
303  template <class T>
305  // Find the right DetSet, and return a reference to it. Throw if
306  // there is none.
307  const_iterator it = this->find(i);
308  if (it == this->end())
310  return *it;
311  }
312 
313  template <class T>
315  _alreadySorted = false; // it's non const
316  return _sets.begin();
317  }
318 
319  template <class T>
321  return _sets.begin();
322  }
323 
324  template <class T>
326  _alreadySorted = false; // it's non const
327  return _sets.end();
328  }
329 
330  template <class T>
332  return _sets.end();
333  }
334 
335  template <class T>
336  inline void DetSetVector<T>::getIds(std::vector<det_id_type>& result) const {
338  this->begin(), this->end(), std::back_inserter(result), std::bind(&DetSet<T>::id, std::placeholders::_1));
339  }
340 
341  template <class T>
343  _sets.shrink_to_fit();
344  if (_alreadySorted)
345  return;
346  typename collection_type::iterator i = _sets.begin();
347  typename collection_type::iterator e = _sets.end();
348  // For each DetSet...
349  for (; i != e; ++i) {
350  i->data.shrink_to_fit();
351  // sort the Detset pointed to by
352  std::sort(i->data.begin(), i->data.end());
353  }
354  }
355 
356  template <class T>
357  inline void DetSetVector<T>::_sort() {
358  std::sort(_sets.begin(), _sets.end());
359  }
360 
361  template <class T>
363  std::vector<void const*>& pointers,
364  FillViewHelperVector& helpers) const {
365  detail::reallyFillView(*this, id, pointers, helpers);
366  }
367 
368  //----------------------------------------------------------------------
369  //
370  // Free function template to support creation of Views.
371 
372  template <class T>
373  inline void fillView(DetSetVector<T> const& obj,
374  ProductID const& id,
375  std::vector<void const*>& pointers,
377  obj.fillView(id, pointers, helpers);
378  }
379 
380  template <class T>
382  static bool const value = true;
383  };
384 
385  // Free swap function
386  template <class T>
388  a.swap(b);
389  }
390 
391 } // namespace edm
392 
393 //specialize behavior of edm::Ref to get access to the 'Det'
394 namespace edm {
395 
396  namespace refhelper {
397  template <typename T>
399  public:
402  using result_type = const T*;
403 
405  return &(*(iContainer.find(iIndex.first)->data.begin() + iIndex.second));
406  }
407  };
408 
409  template <typename T>
410  struct FindTrait<DetSetVector<T>, T> {
412  };
413  } // namespace refhelper
414 
415  //helper function to make it easier to create a edm::Ref
416 
417  template <class HandleT>
419  const HandleT& iHandle, det_id_type iDetID, typename HandleT::element_type::value_type::const_iterator itIter) {
420  typedef typename HandleT::element_type Vec;
422  typename Vec::const_iterator itFound = iHandle->find(iDetID);
423  if (itFound == iHandle->end()) {
425  "an edm::Ref to an edm::DetSetVector was given a DetId, ",
426  iDetID,
427  ", that is not in the DetSetVector");
428  }
429  index += (itIter - itFound->data.begin());
430  if (index >= itFound->data.size()) {
432  "an edm::Ref to a edm::DetSetVector is being made with an interator that is not part of the "
433  "edm::DetSet itself");
434  }
436  iHandle, std::make_pair(iDetID, index));
437  }
438 
439  template <class HandleT>
440  inline Ref<typename HandleT::element_type, typename HandleT::element_type::value_type::value_type>
441  makeRefToDetSetVector(const HandleT& iHandle,
442  det_id_type iDetID,
443  typename HandleT::element_type::value_type::iterator itIter) {
444  typedef typename HandleT::element_type Vec;
445  typename Vec::detset::const_iterator itIter2 = itIter;
446  return makeRefTo(iHandle, iDetID, itIter2);
447  }
448 } // namespace edm
449 #endif
size
Write out results.
collection_type _sets
Definition: DetSetVector.h:186
void _throw_range(det_id_type i)
Definition: DetSetVector.h:69
detset const & const_reference
Definition: DetSetVector.h:99
iterator find(det_id_type id)
Definition: DetSetVector.h:264
Definition: CLHEP.h:16
DetSetVector & operator=(DetSetVector const &other)
void reserve(size_t s)
Definition: DetSetVector.h:147
void swap(DetSetVector< T > &a, DetSetVector< T > &b)
Definition: DetSetVector.h:387
void getIds(std::vector< det_id_type > &result) const
Definition: DetSetVector.h:336
bool empty() const
Return true if we contain no DetSets.
Definition: DetSetVector.h:254
#define CMS_CLASS_VERSION(_version_)
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
assert(be >=bs)
uint16_t size_type
detset & reference
Definition: DetSetVector.h:98
Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type > makeRefToDetSetVector(const HandleT &iHandle, det_id_type iDetID, typename HandleT::element_type::value_type::iterator itIter)
Definition: DetSetVector.h:441
void swap(DetSetVector &other)
std::pair< det_id_type, typename DetSet< T >::collection_type::size_type > second_argument_type
Definition: DetSetVector.h:401
static std::string const input
Definition: EdmProvDump.cc:50
reference find_or_insert(det_id_type id)
Definition: DetSetVector.h:234
static void throwThis(Code category, char const *message0="", char const *message1="", char const *message2="", char const *message3="", char const *message4="")
Definition: EDMException.cc:86
Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type > makeRefTo(const HandleT &iHandle, det_id_type iDetID, typename HandleT::element_type::value_type::const_iterator itIter)
Definition: DetSetVector.h:418
size_type size() const
Return the number of contained DetSets.
Definition: DetSetVector.h:259
def template(fileName, svg, replaceme="REPLACEME")
Definition: svgfig.py:521
Definition: value.py:1
bool insert(Storage &iStorage, ItemType *iItem, const IdTag &iIdTag)
Definition: HCMethods.h:50
std::vector< detset > collection_type
Definition: DetSetVector.h:96
collection_type::iterator iterator
Definition: DetSetVector.h:101
iterator end()
Return the off-the-end iterator.
Definition: DetSetVector.h:325
DetSetVector()
Create an empty DetSetVector.
Definition: DetSetVector.h:194
edm::BoolCache _alreadySorted
Definition: DetSetVector.h:187
uint32_t det_id_type
Definition: DetSet.h:20
DetSet< T > detset
Definition: DetSetVector.h:94
result_type operator()(first_argument_type iContainer, second_argument_type iIndex)
Definition: DetSetVector.h:404
void _sort()
Sort the DetSet in order of increasing DetId.
Definition: DetSetVector.h:357
void fillView(DetSetVector< T > const &obj, ProductID const &id, std::vector< void const *> &pointers, FillViewHelperVector &helpers)
Definition: DetSetVector.h:373
double b
Definition: hdecay.h:118
BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept)
alpaka::Vec< TDim, Idx > Vec
Definition: config.h:23
void insert(detset const &s)
Insert the given DetSet.
Definition: DetSetVector.h:220
void fillView(ProductID const &id, std::vector< void const *> &pointers, FillViewHelperVector &helpers) const
Definition: DetSetVector.h:362
reference operator[](det_id_type i)
Definition: DetSetVector.h:293
HLT enums.
collection_type::size_type size_type
Definition: DetSetVector.h:103
double a
Definition: hdecay.h:119
iterator begin()
Return an iterator to the first DetSet.
Definition: DetSetVector.h:314
collection_type::const_iterator const_iterator
Definition: DetSetVector.h:102
T operator[](int i) const
tmp
align.sh
Definition: createJobs.py:716
long double T
void reallyFillView(COLLECTION const &coll, ProductID const &id, std::vector< void const *> &ptrs, FillViewHelperVector &helpers)
Definition: FillView.h:25
std::vector< std::pair< edm::ProductID, unsigned long > > FillViewHelperVector
unsigned transform(const HcalDetId &id, unsigned transformCode)