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  // What should happen if there is already a DetSet with this
128  // DetId? Right now, it is up to the user *not* to do this. If you
129  // are unsure whether or not your DetId is already in the
130  // DetSetVector, then use 'find_or_insert(id)' instead.
131  void insert(detset const& s);
132 
137 
139  bool empty() const;
140 
142  size_type size() const;
143 
144  // reserve...
145  void reserve(size_t s) { _sets.reserve(s); }
146 
147  // Do we need a short-hand method to return the number of T
148  // instances? If so, do we optimize for size (calculate on the
149  // fly) or speed (keep a current cache)?
150 
154  const_iterator find(det_id_type id) const;
155 
161 
163  iterator begin();
164  const_iterator begin() const;
165 
167  iterator end();
168  const_iterator end() const;
169 
172  void getIds(std::vector<det_id_type>& result) const;
173 
176  void post_insert();
177 
178  void fillView(ProductID const& id, std::vector<void const*>& pointers, FillViewHelperVector& helpers) const;
179 
180  //Used by ROOT storage
182 
183  private:
186 
188  void _sort();
189  };
190 
191  template <class T>
192  inline DetSetVector<T>::DetSetVector() : _sets() {}
193 
194  template <class T>
196  : _sets(), _alreadySorted(alreadySorted) {
197  _sets.swap(input);
198  if (!alreadySorted)
199  _sort();
200  }
201 
202  template <class T>
204  _sets.swap(other._sets);
205  bool tmp = _alreadySorted;
206  _alreadySorted = other._alreadySorted;
207  other._alreadySorted = tmp;
208  }
209 
210  template <class T>
211  inline void DetSetVector<T>::insert(detset const& t) {
212  _alreadySorted = false; // we don't know if the DetSet we're adding is already sorted
213  // Implementation provided by the Performance Task Force.
214  _sets.insert(std::lower_bound(_sets.begin(), _sets.end(), t), t);
215 #if 0
216  // It seems we have to sort on each insertion, because we may
217  // perform lookups during construction.
218  _sets.push_back(t);
219 
220  _sort();
221 #endif
222  }
223 
224  template <class T>
226  // NOTE: we don't have to clear _alreadySorted: the new DS is empty,
227  // and gets inserted in the correct place
228  std::pair<iterator, iterator> p = std::equal_range(_sets.begin(), _sets.end(), id);
229 
230  // If the range isn't empty, we already have the right thing;
231  // return a reference to it...
232  if (p.first != p.second)
233  return *p.first;
234 
235  // Insert the right thing, in the right place, and return a
236  // reference to the newly inserted thing.
237 #if defined(__GXX_EXPERIMENTAL_CXX0X__)
238  return *(_sets.emplace(p.first, id));
239 #else
240  return *(_sets.insert(p.first, detset(id)));
241 #endif
242  }
243 
244  template <class T>
245  inline bool DetSetVector<T>::empty() const {
246  return _sets.empty();
247  }
248 
249  template <class T>
251  return _sets.size();
252  }
253 
254  template <class T>
256  _alreadySorted = false; // it's non const
257  std::pair<iterator, iterator> p = std::equal_range(_sets.begin(), _sets.end(), id);
258  if (p.first == p.second)
259  return _sets.end();
260 
261 // The range indicated by [p.first, p.second) should be exactly of
262 // length 1. It seems likely we don't want to take the time hit of
263 // checking this, but here is the appropriate test... We can turn
264 // it on if we need the debugging aid.
265 #if 0
266  assert(std::distance(p.first, p.second) == 1);
267 #endif
268 
269  return p.first;
270  }
271 
272  template <class T>
274  std::pair<const_iterator, const_iterator> p = std::equal_range(_sets.begin(), _sets.end(), id);
275  if (p.first == p.second)
276  return _sets.end();
277  // The range indicated by [p.first, p.second) should be exactly of
278  // length 1.
279  assert(std::distance(p.first, p.second) == 1);
280  return p.first;
281  }
282 
283  template <class T>
285  _alreadySorted = false; // it's non const
286  // Find the right DetSet, and return a reference to it. Throw if
287  // there is none.
288  iterator it = this->find(i);
289  if (it == this->end())
291  return *it;
292  }
293 
294  template <class T>
296  // Find the right DetSet, and return a reference to it. Throw if
297  // there is none.
298  const_iterator it = this->find(i);
299  if (it == this->end())
301  return *it;
302  }
303 
304  template <class T>
306  _alreadySorted = false; // it's non const
307  return _sets.begin();
308  }
309 
310  template <class T>
312  return _sets.begin();
313  }
314 
315  template <class T>
317  _alreadySorted = false; // it's non const
318  return _sets.end();
319  }
320 
321  template <class T>
323  return _sets.end();
324  }
325 
326  template <class T>
327  inline void DetSetVector<T>::getIds(std::vector<det_id_type>& result) const {
329  this->begin(), this->end(), std::back_inserter(result), std::bind(&DetSet<T>::id, std::placeholders::_1));
330  }
331 
332  template <class T>
334  _sets.shrink_to_fit();
335  if (_alreadySorted)
336  return;
337  typename collection_type::iterator i = _sets.begin();
338  typename collection_type::iterator e = _sets.end();
339  // For each DetSet...
340  for (; i != e; ++i) {
341  i->data.shrink_to_fit();
342  // sort the Detset pointed to by
343  std::sort(i->data.begin(), i->data.end());
344  }
345  }
346 
347  template <class T>
348  inline void DetSetVector<T>::_sort() {
349  std::sort(_sets.begin(), _sets.end());
350  }
351 
352  template <class T>
354  std::vector<void const*>& pointers,
355  FillViewHelperVector& helpers) const {
356  detail::reallyFillView(*this, id, pointers, helpers);
357  }
358 
359  //----------------------------------------------------------------------
360  //
361  // Free function template to support creation of Views.
362 
363  template <class T>
364  inline void fillView(DetSetVector<T> const& obj,
365  ProductID const& id,
366  std::vector<void const*>& pointers,
368  obj.fillView(id, pointers, helpers);
369  }
370 
371  template <class T>
373  static bool const value = true;
374  };
375 
376  // Free swap function
377  template <class T>
379  a.swap(b);
380  }
381 
382 } // namespace edm
383 
384 //specialize behavior of edm::Ref to get access to the 'Det'
385 namespace edm {
386 
387  namespace refhelper {
388  template <typename T>
390  public:
393  using result_type = const T*;
394 
396  return &(*(iContainer.find(iIndex.first)->data.begin() + iIndex.second));
397  }
398  };
399 
400  template <typename T>
401  struct FindTrait<DetSetVector<T>, T> {
403  };
404  } // namespace refhelper
405 
406  //helper function to make it easier to create a edm::Ref
407 
408  template <class HandleT>
410  const HandleT& iHandle, det_id_type iDetID, typename HandleT::element_type::value_type::const_iterator itIter) {
411  typedef typename HandleT::element_type Vec;
413  typename Vec::const_iterator itFound = iHandle->find(iDetID);
414  if (itFound == iHandle->end()) {
416  "an edm::Ref to an edm::DetSetVector was given a DetId, ",
417  iDetID,
418  ", that is not in the DetSetVector");
419  }
420  index += (itIter - itFound->data.begin());
421  if (index >= itFound->data.size()) {
423  "an edm::Ref to a edm::DetSetVector is being made with an interator that is not part of the "
424  "edm::DetSet itself");
425  }
427  iHandle, std::make_pair(iDetID, index));
428  }
429 
430  template <class HandleT>
431  inline Ref<typename HandleT::element_type, typename HandleT::element_type::value_type::value_type>
432  makeRefToDetSetVector(const HandleT& iHandle,
433  det_id_type iDetID,
434  typename HandleT::element_type::value_type::iterator itIter) {
435  typedef typename HandleT::element_type Vec;
436  typename Vec::detset::const_iterator itIter2 = itIter;
437  return makeRefTo(iHandle, iDetID, itIter2);
438  }
439 } // namespace edm
440 #endif
size
Write out results.
collection_type _sets
Definition: DetSetVector.h:184
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:255
Definition: CLHEP.h:16
void reserve(size_t s)
Definition: DetSetVector.h:145
void swap(DetSetVector< T > &a, DetSetVector< T > &b)
Definition: DetSetVector.h:378
void getIds(std::vector< det_id_type > &result) const
Definition: DetSetVector.h:327
bool empty() const
Return true if we contain no DetSets.
Definition: DetSetVector.h:245
#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:432
void swap(DetSetVector &other)
std::pair< det_id_type, typename DetSet< T >::collection_type::size_type > second_argument_type
Definition: DetSetVector.h:392
static std::string const input
Definition: EdmProvDump.cc:50
reference find_or_insert(det_id_type id)
Definition: DetSetVector.h:225
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:409
size_type size() const
Return the number of contained DetSets.
Definition: DetSetVector.h:250
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:316
DetSetVector()
Create an empty DetSetVector.
Definition: DetSetVector.h:192
edm::BoolCache _alreadySorted
Definition: DetSetVector.h:185
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:395
void _sort()
Sort the DetSet in order of increasing DetId.
Definition: DetSetVector.h:348
void fillView(DetSetVector< T > const &obj, ProductID const &id, std::vector< void const *> &pointers, FillViewHelperVector &helpers)
Definition: DetSetVector.h:364
double b
Definition: hdecay.h:120
BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept)
alpaka::Vec< TDim, Idx > Vec
Definition: config.h:24
void insert(detset const &s)
Insert the given DetSet.
Definition: DetSetVector.h:211
void fillView(ProductID const &id, std::vector< void const *> &pointers, FillViewHelperVector &helpers) const
Definition: DetSetVector.h:353
reference operator[](det_id_type i)
Definition: DetSetVector.h:284
HLT enums.
collection_type::size_type size_type
Definition: DetSetVector.h:103
double a
Definition: hdecay.h:121
iterator begin()
Return an iterator to the first DetSet.
Definition: DetSetVector.h:305
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)