ATLAS Offline Software
DetectorDescription/Identifier/src/Range.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 
6 // gcc12 gives false positive warnings from copying boost::small_vector,
7 // as the sort operation in show_all_ids.
8 #if __GNUC__ >= 12
9 # pragma GCC diagnostic ignored "-Wstringop-overread"
10 #endif
11 
12 
13 #include "Identifier/Range.h"
14 #include <algorithm>
15 #include <cstdio>
16 #include <string>
17 #include <vector>
18 
19 #include <limits>
20 #include <iostream>
21 #include <iomanip>
22 #include <stdexcept>
23 #include <cassert>
24 
25 
26 
27 //--------------------------------------------------------------------------
29  if (index >= m_fields.size ()){
30  static const field f;
31  return (f);
32  }
33  return (m_fields[index]);
34 }
35 
36 //-----------------------------------------------
38  if (start < other.fields ()) {
39  field_vector::const_iterator it = other.m_fields.begin ();
40  it += start;
41  m_fields.insert (m_fields.end (), it, other.m_fields.end ());
42  }
43 }
44 
45 Range::Range(const std::string & text):Range(){
46  if (text.empty()) return;
47  std::istringstream in(text);
48  in>>*this;
49 }
50 
51 //-----------------------------------------------
53  // Construct from a root (i.e. add wild card for below)
54  build (root);
55 }
56 
57 //-----------------------------------------------
58 void Range::build (const std::string& text) {
59  if (text.empty()) return;
60  std::istringstream in(text);
61  in>>*this;
62 }
63 
64 //-----------------------------------------------
66  // Construct from a root
67  m_fields.clear ();
68  for (size_type i = 0; i < root.fields (); ++i){
69  m_fields.emplace_back(root[i]);
70  }
71 }
72 
73  // Modifications
74 //-----------------------------------------------
75 void Range::add () {
76  m_fields.emplace_back();
77 }
78 
79 //-----------------------------------------------
81  m_fields.emplace_back (value);
82 }
83 
84 //-----------------------------------------------
85 void Range::add (element_type minimum, element_type maximum) {
86  m_fields.emplace_back (minimum, maximum);
87 }
88 
89 
90 
92 void Range::add (const field& f) {
93  m_fields.emplace_back(f);
94 }
95 
97 void Range::add (field&& f) {
98  m_fields.emplace_back(std::move(f));
99 }
100 
102 void Range::add (const Range& subrange) {
103  for (size_t i = 0; i < subrange.fields (); ++i) {
104  const field& f = subrange[i];
105  m_fields.push_back (f);
106  }
107 }
108 
109 void Range::add (Range&& subrange) {
110  if (m_fields.empty())
111  m_fields.swap (subrange.m_fields);
112  else {
113  size_t sz = subrange.m_fields.size();
114  m_fields.reserve (m_fields.size() + sz);
115  for (size_t i = 0; i < sz; ++i) {
116  m_fields.emplace_back (std::move(subrange.m_fields[i]));
117  }
118  }
119 }
120 
121 
122 
123 
124 //-----------------------------------------------
125 void Range::clear () {
126  m_fields.clear ();
127 }
128 
129 //-----------------------------------------------
130 int Range::match (const ExpandedIdentifier& id) const {
131  size_type my_fields = m_fields.size ();
132  const size_type id_fields = id.fields ();
133  // Remove trailing wild cards since they are meaningless.
134  while ((my_fields > 1) &&
135  (m_fields[my_fields-1].empty())){
136  my_fields--;
137  }
138  // Ranges with only wild cards always match.
139  if (my_fields == 0) return (1);
140  // More fields in the range than in the identifier will never match.
141  //if (my_fields > id_fields) return (0);
142 
143  // Allow match for id shorter than range - assume "wildcards" for
144  // missing id fields
145  size_type nfields = (my_fields > id_fields) ? id_fields : my_fields;
146  // Test fields one by one.
147  for (size_type field_number = 0; field_number < nfields; field_number++) {
148  const field& f = m_fields[field_number];
149  if (!f.match (id[field_number])) return (0);
150  }
151  // All conditions match.
152  return (1);
153 }
154 
155 // Accessors
156 
157 //-----------------------------------------------
159  size_type my_fields = m_fields.size ();
161  // Remove trailing wild cards since they are meaningless.
162  while ((my_fields > 1) &&
163  (m_fields[my_fields-1].empty())){
164  my_fields--;
165  }
166  // Ranges with only wild cards: set first field of min to 0
167  if (my_fields == 0) {
168  result << 0;
169  return result; // Don't combine these two lines --- it inhibits RVO.
170  }
171  // Copy fields to result - look for wild cards
172  for (size_type field_number = 0; field_number < my_fields; field_number++) {
173  const field& f = m_fields[field_number];
174  if (f.empty()){
175  // Wilds card -> set field to 0
176  result << 0;
177  } else {
178  // Valued field
179  result << f.get_minimum ();
180  }
181  }
182 
183  return (result);
184 }
185 
186 //-----------------------------------------------
188  size_type my_fields = m_fields.size ();
190  // Remove all by the last trailing wild card, extra ones are
191  // meaningless.
192  while ((my_fields > 1) &&
193  (m_fields[my_fields-1].empty())) {
194  my_fields--;
195  }
196 
197  // Ranges with only wild cards: set first field of min to ExpandedIdentifier::max_value
198  if (my_fields == 0) {
200  return result; // Don't combine these two lines --- it inhibits RVO.
201  }
202 
203  // Copy fields to result - look for wild cards
204  for (size_type field_number = 0; field_number < my_fields; field_number++) {
205  const field& f = m_fields[field_number];
206  if (f.empty()) {
207  // Wilds card
208  if (field_number == 0) {
209  // For 1st field set it to ExpandedIdentifier::max_value
211  } else {
212  //
213  // For subsequent fields, set do ++ for field-1
214  // This requires rebuilding the result
215  //
216  ExpandedIdentifier new_result;
217 
218  for (size_type new_field_number = 0;
219  new_field_number < (field_number - 1);
220  ++new_field_number) {
221  new_result << result[new_field_number];
222  }
223 
224  element_type last = result[field_number - 1];
225  new_result << ((ExpandedIdentifier::max_value == last) ? last : last + 1);
226  new_result << 0;
227  assert ( result.fields () == new_result.fields () );
228  result = new_result;
229  }
230  } else {
231  // Normal field
232  result << f.get_maximum ();
233  }
234  }
235 
236  return (result);
237 }
238 
240  size_type result = 1;
241  const Range& me = *this;
242  for (size_type i = 0; i < fields (); ++i) {
243  const field& f = me[i];
244  result *= f.get_indices ();
245  }
246  return (result);
247 }
248 
249 
254  size_type result = 0;
255  if (id.fields() != fields()) return (result);
256  const Range& me = *this;
257  // Check if we are above or below this range
258  if (id < minimum()) return 0;
259  if (maximum() < id) return cardinality();
260  // Collect the indices of a match
261  std::vector<size_type> indices(id.fields (), 0);
262  bool is_match = true;
263  size_type level = 0;
264  for (; level < id.fields (); ++level) {
265  const field& f = me[level];
266  // Require all fields to be bounded or enumerated
267  if (f.empty()) return 0;
268  if (f.isEnumerated()) {
269  // Continue testing for a match
270  size_type max = f.get_values().size() - 1;
271  if (f.get_values()[max] < id[level]) {
272  // above max
273  is_match = false;
274  indices[level] = max + 1;
275  } else {
276  for (size_type j = 0; j < f.get_values().size(); ++j) {
277  if (id[level] <= f.get_values()[j]) {
278  if (id[level] != f.get_values()[j]) {
279  // between two values or below first one
280  is_match = false;
281  }
282  indices[level] = j;
283  break;
284  }
285  }
286  }
287  } else {
288  if (f.get_maximum() < id[level]) {
289  // above max
290  is_match = false;
291  indices[level] = f.get_maximum() - f.get_minimum() + 1;
292  } else if (id[level] < f.get_minimum()) {
293  // below min
294  is_match = false;
295  indices[level] = 0;
296  } else {
297  indices[level] = id[level] - f.get_minimum();
298  }
299  }
300  if (!is_match) break;
301  }
302 
303  // Calculate the cardinality
304  if (level < id.fields ()) ++level;
305  for (size_type j = 0; j < level; ++j) {
306  size_type card = indices[j];
307  for (size_type k = j + 1; k < id.fields(); ++k) {
308  const field& f = me[k];
309  card *= f.get_indices();
310  }
311  result += card;
312  }
313  return result;
314 }
315 
316 
323 bool Range::overlaps_with (const Range& other) const {
324  const Range& me = *this;
325  if ((fields () == 0) || (other.fields () == 0)) return (false);
326  for (size_type i = 0; i < std::min (fields (), other.fields ()); ++i){
327  const field& f1 = me[i];
328  const field& f2 = other[i];
329  if (!f1.overlaps_with (f2)) return (false);
330  }
331  return (true);
332 }
333 
334 //-----------------------------------------------
335 void Range::show () const {
336  show (std::cout);
337 }
338 
339 void Range::show (std::ostream& s) const {
340  const Range& me = *this;
341  s << (std::string) me << " (";
342  int allbits = 0;
343  for (size_type i = 0; i < fields (); ++i) {
344  const field& f = me[i];
345  if (i > 0) s << "+";
346  size_type indices = f.get_indices ();
347  int bits = 1;
348  indices--;
349  if (indices > 0) {
350  bits = 0;
351  while (indices > 0){
352  indices /= 2;
353  bits++;
354  }
355  }
356  allbits += bits;
357  s << bits;
358  }
359  s << "=" << allbits << ") ";
360 }
361 
362 //-----------------------------------------------
363 Range::operator std::string () const {
364  std::string result;
365  size_type my_fields = m_fields.size ();
366  // Remove trailing wild cards since they are meaningless.
367  while ((my_fields > 1) &&
368  (m_fields[my_fields-1].empty())) {
369  my_fields--;
370  }
371  if (my_fields == 0) return (result);
372  // print fields one by one.
373  for (size_type field_number = 0; field_number < my_fields; field_number++) {
374  const field& f = m_fields[field_number];
375  if (field_number > 0) result += "/";
376  result += (std::string) f;
377  }
378  return (result);
379 }
380 
381 //-----------------------------------------------
382 bool
384  if (m_fields.size() != other.m_fields.size()) return false;
385  field_vector::const_iterator it1 = m_fields.begin();
386  field_vector::const_iterator it2 = other.m_fields.begin();
387  field_vector::const_iterator last = m_fields.end();
388  for (; it1 != last; ++it1, ++it2) {
389  if ((*it1) != (*it2)) return false;
390  }
391  return (true);
392 }
393 
394 
395 
396 
397 
398 
399 std::ostream &
400 operator << (std::ostream &out, const Range &r){
401  out<<std::string(r);
402  return out;
403 }
404 
405 std::istream &
406 operator >> (std::istream &in, Range &r){
407  r.clear ();
408  for (int c{}; c!=EOF;c=in.peek()){
410  in>>field;
411  r.add(field);
412  if (int c = in.peek();(c == '/') or (c ==' ')){
413  in.ignore();
414  }
415  }
416  return in;
417 }
beamspotman.r
def r
Definition: beamspotman.py:676
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
Range::clear
void clear()
Modifications.
Definition: DetectorDescription/Identifier/src/Range.cxx:125
fitman.sz
sz
Definition: fitman.py:527
get_generator_info.result
result
Definition: get_generator_info.py:21
max
#define max(a, b)
Definition: cfImp.cxx:41
Range::operator==
bool operator==(const Range &other) const
Definition: DetectorDescription/Identifier/src/Range.cxx:383
Range::size_type
ExpandedIdentifier::size_type size_type
Definition: DetectorDescription/Identifier/Identifier/Range.h:33
Range::match
int match(const ExpandedIdentifier &id) const
Match an identifier.
Definition: DetectorDescription/Identifier/src/Range.cxx:130
Range::show
void show() const
Definition: DetectorDescription/Identifier/src/Range.cxx:335
index
Definition: index.py:1
Trk::indices
std::pair< long int, long int > indices
Definition: AlSymMatBase.h:24
Range::maximum
ExpandedIdentifier maximum() const
Definition: DetectorDescription/Identifier/src/Range.cxx:187
mergePhysValFiles.start
start
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:14
Range.h
skel.it
it
Definition: skel.GENtoEVGEN.py:396
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
ExpandedIdentifier
Definition: DetectorDescription/Identifier/Identifier/ExpandedIdentifier.h:102
athena.value
value
Definition: athena.py:124
ExpandedIdentifier::fields
size_type fields() const
sendEI_SPB.root
root
Definition: sendEI_SPB.py:34
ReadOfcFromCool.field
field
Definition: ReadOfcFromCool.py:48
ExpandedIdentifier::max_value
static constexpr element_type max_value
Definition: DetectorDescription/Identifier/Identifier/ExpandedIdentifier.h:115
empty
bool empty(TH1 *h)
Definition: computils.cxx:294
python.iconfTool.models.loaders.level
level
Definition: loaders.py:20
read_hist_ntuple.f2
f2
Definition: read_hist_ntuple.py:20
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
Range::m_fields
field_vector m_fields
Definition: DetectorDescription/Identifier/Identifier/Range.h:145
Range::minimum
ExpandedIdentifier minimum() const
min and max ExpandedIdentifiers (if they exist, ie.
Definition: DetectorDescription/Identifier/src/Range.cxx:158
operator<<
std::ostream & operator<<(std::ostream &out, const Range &r)
Definition: DetectorDescription/Identifier/src/Range.cxx:400
lumiFormat.i
int i
Definition: lumiFormat.py:85
DetDescrDictionaryDict::it1
std::vector< HWIdentifier >::iterator it1
Definition: DetDescrDictionaryDict.h:17
Range::Range
Range()=default
jobOptions.card
card
Definition: jobOptions.GenevaPy8_Zmumu.py:11
ReadOfcFromCool.nfields
nfields
Definition: ReadOfcFromCool.py:114
hist_file_dump.f
f
Definition: hist_file_dump.py:135
operator>>
std::istream & operator>>(std::istream &in, Range &r)
Definition: DetectorDescription/Identifier/src/Range.cxx:406
Range::fields
size_type fields() const
Definition: DetectorDescription/Identifier/Identifier/Range.h:151
min
#define min(a, b)
Definition: cfImp.cxx:40
Range::operator[]
const field & operator[](size_type index) const
Access the field elements.
Definition: DetectorDescription/Identifier/src/Range.cxx:28
Range
A Range describes the possible ranges for the field values of an ExpandedIdentifier.
Definition: DetectorDescription/Identifier/Identifier/Range.h:29
Range::add
void add()
Add a wild card field.
Definition: DetectorDescription/Identifier/src/Range.cxx:75
InDetDD::other
@ other
Definition: InDetDD_Defs.h:16
IdentifierField
This is the individual specification for the range of one ExpandedIdentifier IdentifierField.
Definition: IdentifierField.h:21
Range::overlaps_with
bool overlaps_with(const Range &other) const
Check if two Ranges overlap.
Definition: DetectorDescription/Identifier/src/Range.cxx:323
makeTransCanvas.text
text
Definition: makeTransCanvas.py:11
Range::cardinality
size_type cardinality() const
Computes a possible cardinality :
Definition: DetectorDescription/Identifier/src/Range.cxx:239
Range::build
void build(const std::string &text)
Build Range from a textual description.
Definition: DetectorDescription/Identifier/src/Range.cxx:58
python.compressB64.c
def c
Definition: compressB64.py:93
Range::element_type
ExpandedIdentifier::element_type element_type
Definition: DetectorDescription/Identifier/Identifier/Range.h:32
fitman.k
k
Definition: fitman.py:528
read_hist_ntuple.f1
f1
Definition: read_hist_ntuple.py:4
Range::cardinalityUpTo
size_type cardinalityUpTo(const ExpandedIdentifier &id) const
Get the cardinality from the beginning up to the given ExpandedIdentifier.
Definition: DetectorDescription/Identifier/src/Range.cxx:253