ATLAS Offline Software
IdentifierField.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
7 #include <algorithm>
8 #include <iostream>
9 #include <bit> //std::bit_width
10 #include <array>
11 #include <cctype> //std::isspace
12 #include <format>
13 #include <tuple> //for std::tie
14 #include <functional> //std::less
15 
16 using namespace Identifier;
17 
18 namespace{
19 template<class SetA, class SetB, typename Compare = std::less<>>
20 bool
21 share_element(SetA&& setA, SetB&& setB, Compare comp = Compare{}){
22  auto xA = setA.begin();
23  auto xB = setB.begin();
24  while (xA != setA.end() && xB != setB.end()){
25  if (comp(*xA, *xB)) {
26  ++xA;
27  } else if (comp(*xB, *xA)) {
28  ++xB;
29  } else {
30  return true;
31  }
32  }
33  return false;
34 }
35 
36 }
37 
38 
39 //------------------------------------------------------------------
41  size_t indices = get_indices ();
42  if (--indices) return std::bit_width(indices);
43  return 1;
44 }
45 
46 
47 //-----------------------------------------------
50  // Only both_bounded and enumerated are valid to calculate the
51  // index.
52  // both_bounded if the more frequent case and so comes first.
53  if (isBounded()) {
54  return (value - m_minimum);
55  }
56  const auto & v = get_values();
57  if (v.size()==1) return 0;
58  if (not m_indexes.empty()) {
59  // Table has been created, do simple lookup
60  assert (value >= m_minimum && value - m_minimum < (int)m_indexes.size());
61  return (m_indexes.at(value - m_minimum));
62  } else {
63  auto it = std::ranges::find(v, value);
64  if (it != v.end()) return std::distance(v.begin(), it);
65  }
66  return 0;
67 }
68 
69 //-----------------------------------------------
70 bool
72  if (isBounded()) {
73  return ((value >= m_minimum) && (value <= m_maximum));
74  }
75  if (m_empty) return true;
76  const auto & v = get_values();
77  return (std::ranges::find(v, value)!=v.end());
78 }
79 
80 
81 
82 //-----------------------------------------------
84  :
85  m_minimum(value),
86  m_maximum(value),
88  m_empty{false}{
89  //
90 }
91 
92 //-----------------------------------------------
94  set(minimum, maximum);
95 }
96 
97 
100  set(values);
101 }
102 
103 
104 //-----------------------------------------------
105 bool
107  if (m_empty){
108  previous = current - 1;
109  return (current != minimum_possible);
110  }
111  if (isBounded()){
112  if (current == m_minimum) {
115  return (true);
116  }
119  return (true);
120  }
121  previous = current;
122  return (false);
123  }
124  previous = current - 1;
125  return (true);
126  }
127  const auto & values= get_values();
129  if (index == 0) {
131  previous = values.back();
132  return (true);
133  }
136  return (true);
137  }
138  previous = current;
139  return (false);
140  }
141  --index;
142  previous = values[index];
143  return true;
144 }
145 
146 
147 //-----------------------------------------------
148 bool
150  if (m_empty){
151  next = current + 1;
152  return (current != maximum_possible);
153  }
154 
155  if (isBounded()){
156  if (current == m_maximum) {
158  next = m_minimum;
159  return (true);
160  }
161  if (has_next == m_continuation_mode) {
162  next = m_next;
163  return (true);
164  }
165  next = current;
166  return (false);
167  }
168  next = current + 1;
169  return (true);
170  }
171  const auto & values= get_values();
173  if ((index == values.size() - 1) || (index == 0 && current != values.front())) {
175  next = values.front();
176  return (true);
177  }
178  if (has_next == m_continuation_mode) {
179  next = m_next;
180  return (true);
181  }
182  next = current;
183  return (false);
184  }
185  ++index;
186  next = values[index];
187  return true;
188 }
189 
190 
191 
192 //-----------------------------------------------
193 bool
195  if (m_empty or other.m_empty) return true;
196  //
197  if (isBounded() and other.isBounded()){
198  return ((m_minimum <= other.m_maximum) && (m_maximum >= other.m_minimum));
199  }
200  //
201  if (isBounded() and other.isEnumerated() ){
202  const element_vector& ev = other.get_values();
203  for (const auto & v: ev) {
204  if (v >= m_minimum and v<= m_maximum) return (true);
205  }
206  return false;
207  } else if (isEnumerated() and other.isBounded()){
208  const element_vector& ev = get_values();
209  for (const auto & v: ev){
210  if ((v >= other.m_minimum) and (v <= other.m_maximum)) return (true);
211  }
212  return false;
213  }
214  // Both fields are enumerated only if there is possibility of overlap
215  if ((m_minimum <= other.m_maximum) && (m_maximum >= other.m_minimum)) {
216  return share_element(get_values(), other.get_values());
217  }
218  return (false);
219 }
220 
221 
222 //-----------------------------------------------
223 void
225  m_minimum = 0;
226  m_maximum = 0;
227  m_previous = 0;
228  m_next = 0;
231  m_indexes.clear();
232  m_empty = true;
233 }
234 
235 //-----------------------------------------------
236 void
238  if (minimum == maximum) {
239  add_value(minimum);
240  } else {
241  std::tie(m_minimum,m_maximum) = std::minmax(minimum,maximum);
243  m_size = m_maximum - m_minimum + 1;
244  }
245  m_empty=false;
246 }
247 
248 //-----------------------------------------------
249 void
251  if (auto * p = dataPtr<element_vector>(); !p) {
252  clear();
253  m_data = element_vector(1,value);//now its enumerated
254  m_size = 1;
255  } else {
256  //check whether value already exists in the enumeration vector
257  if (std::ranges::binary_search(*p, value)) return;
258  p->push_back(value);
259  std::ranges::sort(*p);
260  m_size = p->size();
261  }
262  m_minimum = get_values().front();
263  m_maximum = get_values().back();
264  m_empty = false;
265 }
266 
267 //-----------------------------------------------
268 void
269 IdentifierField::set(const std::vector <element_type>& values) {
270  auto * p = dataPtr<element_vector>();
271  if (not p) {
272  clear();
273  p = dataPtr<element_vector>();
274  }
275  p->insert(p->end(), values.begin(), values.end());
276  std::ranges::sort (*p);
277  //ensure duplicates are taken out
278  p->erase( std::unique( p->begin(), p->end() ), p->end() );
279  m_minimum = p->front();
280  m_maximum = p->back();
281  m_empty=false;
282  m_size = p->size();
283 }
284 
285 //-----------------------------------------------
286 void
287 IdentifierField::set(bool wraparound) {
288  if (wraparound) {
290  }
291 }
292 
293 //-----------------------------------------------
294 void
298  } else {
300  }
301  m_next = next;
302 }
303 
304 
305 //-----------------------------------------------
306 void
308  if (has_next == m_continuation_mode) {
310  } else {
312  }
314 }
315 
316 
317 //-----------------------------------------------
318 void
320  if (m_empty or other.m_empty){
321  clear();
322  m_size = 1;
323  return;
324  }
325  if (isEnumerated() and other.isEnumerated()){
326  set(other.get_values ());
327  return;
328  }
335  // all other cases...
336  const auto min = std::min(m_minimum, other.m_minimum);
337  const auto max = std::max(m_maximum, other.m_maximum);
338  set(min, max);
339 }
340 
341 
342 //-----------------------------------------------
343 IdentifierField::operator std::string () const {
344  std::string result;
345  if (m_empty) {
346  result = "*";
347  } else {
348  const auto & [minimum, maximum] = get_minmax();
349  if (minimum == maximum) {
350  result = std::to_string(minimum);
351  } else {
352  if (isEnumerated()) {
353  std::string prefix;
354  for (size_type i = 0; i < get_indices (); ++i) {
355  result += prefix+std::to_string(get_value_at(i));
356  prefix = ",";
357  }
358  } else {
359  result = std::format("{}:{}", minimum, maximum);
360  }
361  }
362  }
363  return result;
364 }
365 
366 //-----------------------------------------------
367 bool
369  if (m_data != other.m_data) return false;
370  return (true);
371 }
372 
373 
374 //-----------------------------------------------
375 void
377  std::cout << "min/max " << m_minimum << " " << m_maximum << " ";
378  std::cout << "values ";
379  for (const auto& v: get_values()) {
380  std::cout << v << " ";
381  }
382  std::cout << "indexes ";
383  for (const auto & idx: m_indexes) {
384  std::cout << idx << " ";
385  }
386  std::cout << "indices " << m_size << " ";
387  std::cout << "prev " << m_previous << " ";
388  std::cout << "next " << m_next << " ";
389  std::cout << "mode ";
390  if (m_empty){
391  std::cout << "unbounded ";
392  }else if (isBounded()){
393  std::cout << "both_bounded ";
394  }else if (isEnumerated()) {
395  std::cout << "enumerated ";
396  }
397  std::cout << "cont mode ";
398  switch (m_continuation_mode) {
399  case IdentifierField::none:
400  std::cout << "none ";
401  break;
403  std::cout << "has_next ";
404  break;
406  std::cout << "has_previous ";
407  break;
409  std::cout << "has_both ";
410  break;
412  std::cout << "has_wrap_around ";
413  break;
414  }
415  std::cout << std::endl;
416 }
417 
418 
419 
420 //-----------------------------------------------
421 void
425 }
426 
427 
428 //-----------------------------------------------
429 bool
431  if (m_empty) return false;
432  if (isEnumerated()) {
433  //the enumerated values are kept sorted
434  if (m_size-1 == static_cast<size_type>(m_maximum - m_minimum)){
436  return true;
437  }
438  }
439  return false;
440 }
441 
442 //-----------------------------------------------
443 void
445  if (m_empty) return;
447  if (isEnumerated()) {
449  // return if we are over the maximum desired vector table size
450  if (size > m_maxNumberOfIndices) {
451  m_indexes.clear();
452  return;
453  }
454  // Set up vectors for decoding
455  m_indexes = std::vector<size_type>(size, 0);
456  size_type index{};
457  int i{};
458  auto &v = std::get<element_vector>(m_data);
459  for (const auto & thisValue: v) {
460  if (const auto idx=(thisValue - m_minimum); idx < (int)size) {
461  m_indexes[idx] = index;
462  index++;
463  } else {
464  std::cout << "size, value, index, i "
465  << size << " " << thisValue << " "
466  << index << " " << i++ << " min, max "
467  << m_minimum << " "
468  << m_maximum
469  << std::endl;
470  }
471  }
472  }
473 }
474 
475 std::ostream &
476 operator << (std::ostream &out, const IdentifierField &c){
477  out<<std::string(c);
478  return out;
479 }
480 
481 //stream extraction allows to read from text (e.g. text file)
482 std::istream &
483 operator >> (std::istream &is, IdentifierField &idf){
484  idf.clear();
485  while (std::isspace(is.peek())){is.ignore();}
486  char c = is.peek();
487  if (c =='*'){
488  is.ignore();
489  //do nothing; the 'clear' set idf to unbounded
490  } else if (isDigit(c)){
491  if (c =='+') is.ignore();
492  int v = parseStreamDigits(is);//'is' ptr is incremented
493  c = is.peek();
494  //possible: bound, list
495  if (c == ','){ //found comma, so definitely list
496  is.ignore();
497  std::vector<int> vec(1,v);
498  const auto & restOfList = parseStreamList(is);
499  vec.insert(vec.end(), restOfList.begin(), restOfList.end());
500  idf.set(vec);
501  } else if (c == ':'){ //bounded
502  is.ignore();
503  c=is.peek(); //peek char after the colon
504  if (isDigit(c)){ //bounded
505  int v1 = parseStreamDigits(is);
506  idf.set(v,v1);
507  }
508  } else { //remaining alternative: single number
509  idf.add_value(v);
510  }
511  } else {
512  std::string msg{"Stream extraction for IdentifierField: "};
513  std::string remains;
514  is >> remains;
515  msg+=remains;
516  throw std::invalid_argument(msg);
517  }
518  return is;
519 }
520 
plotting.yearwise_luminosity_vs_mu.comp
comp
Definition: yearwise_luminosity_vs_mu.py:23
fillPileUpNoiseLumi.current
current
Definition: fillPileUpNoiseLumi.py:52
get_generator_info.result
result
Definition: get_generator_info.py:21
vtune_athena.format
format
Definition: vtune_athena.py:14
IdentifierField::get_bits
size_type get_bits() const
Definition: IdentifierField.cxx:40
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
IdentifierField::element_type
ExpandedIdentifier::element_type element_type
Definition: IdentifierField.h:23
IdentifierField::overlaps_with
bool overlaps_with(const IdentifierField &other) const
Check whether two IdentifierFields overlap.
Definition: IdentifierField.cxx:194
index
Definition: index.py:1
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
m_data
std::vector< T > m_data
Definition: TrackTruthMatchingBaseAlg.cxx:660
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
IdentifierField::m_maxNumberOfIndices
static constexpr int m_maxNumberOfIndices
Definition: IdentifierField.h:120
Trk::indices
std::pair< long int, long int > indices
Definition: AlSymMatBase.h:24
Identifier::parseStreamDigits
IdentifierField::element_type parseStreamDigits(std::istream &is)
Definition: IdentifierFieldParser.cxx:21
skel.it
it
Definition: skel.GENtoEVGEN.py:401
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
IdentifierField::clear
void clear()
Set methods.
Definition: IdentifierField.cxx:224
IdentifierField::m_maximum
element_type m_maximum
Definition: IdentifierField.h:130
athena.value
value
Definition: athena.py:124
operator>>
std::istream & operator>>(std::istream &is, IdentifierField &idf)
Definition: IdentifierField.cxx:483
IdentifierField::get_values
const element_vector & get_values() const
Definition: IdentifierField.h:71
IdentifierField::set
void set(element_type minimum, element_type maximum)
Definition: IdentifierField.cxx:237
vec
std::vector< size_t > vec
Definition: CombinationsGeneratorTest.cxx:9
IdentifierField::has_both
@ has_both
Definition: IdentifierField.h:36
IdentifierField::m_continuation_mode
continuation_mode m_continuation_mode
Definition: IdentifierField.h:137
Identifier::parseStreamList
IdentifierField::element_vector parseStreamList(std::istream &is)
Definition: IdentifierFieldParser.cxx:37
IdentifierField::set_next
void set_next(int next)
Definition: IdentifierField.cxx:295
IdentifierField::m_next
element_type m_next
Definition: IdentifierField.h:135
IdentifierField::create_index_table
void create_index_table()
Create index table from value table.
Definition: IdentifierField.cxx:444
python.Bindings.values
values
Definition: Control/AthenaPython/python/Bindings.py:805
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
CxxUtils::vec
typename vecDetail::vec_typedef< T, N >::type vec
Define a nice alias for the vectorized type.
Definition: vec.h:207
IdentifierField::m_size
size_type m_size
Definition: IdentifierField.h:133
IdentifierField::match
bool match(element_type value) const
The basic match operation.
Definition: IdentifierField.cxx:71
IdentifierFieldParser.h
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
ev
int ev
Definition: globals.cxx:25
IdentifierField::get_value_index
size_type get_value_index(element_type value) const
Definition: IdentifierField.cxx:49
Identifier::isDigit
bool isDigit(const char c)
Definition: IdentifierFieldParser.cxx:16
IdentifierField::operator==
bool operator==(const IdentifierField &other) const
Definition: IdentifierField.cxx:368
fillPileUpNoiseLumi.next
next
Definition: fillPileUpNoiseLumi.py:52
lumiFormat.i
int i
Definition: lumiFormat.py:85
IdentifierField::m_previous
element_type m_previous
Definition: IdentifierField.h:134
IdentifierField::minimum_possible
static constexpr auto minimum_possible
Definition: IdentifierField.h:28
python.LArMinBiasAlgConfig.int
int
Definition: LArMinBiasAlgConfig.py:59
IdentifierField::m_minimum
element_type m_minimum
Definition: IdentifierField.h:129
IdentifierField::m_data
std::variant< element_vector, BoundedRange > m_data
Definition: IdentifierField.h:131
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
IdentifierField::get_next
bool get_next(element_type current, element_type &next) const
Definition: IdentifierField.cxx:149
operator<<
std::ostream & operator<<(std::ostream &out, const IdentifierField &c)
Definition: IdentifierField.cxx:476
IdentifierField::isEnumerated
bool isEnumerated() const
Definition: IdentifierField.h:117
ExpandedIdentifier::size_type
boost::container::small_vector< element_type, 12 >::size_type size_type
Definition: DetectorDescription/Identifier/Identifier/ExpandedIdentifier.h:112
IdentifierField::element_vector
std::vector< element_type > element_vector
Definition: IdentifierField.h:25
IdentifierField::none
@ none
Definition: IdentifierField.h:33
IdentifierField.h
IdentifierField::set_previous
void set_previous(int previous)
Definition: IdentifierField.cxx:307
IdentifierField::check_for_both_bounded
bool check_for_both_bounded()
Check mode - switch from enumerated to both_bounded if possible.
Definition: IdentifierField.cxx:430
IdentifierField::size_type
ExpandedIdentifier::size_type size_type
Definition: IdentifierField.h:24
IdentifierField::maximum_possible
static constexpr auto maximum_possible
Definition: IdentifierField.h:29
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
IdentifierField::isBounded
bool isBounded() const
Definition: IdentifierField.h:116
IdentifierField::has_wrap_around
@ has_wrap_around
Definition: IdentifierField.h:37
python.PyAthena.v
v
Definition: PyAthena.py:154
IdentifierField::m_empty
bool m_empty
Definition: IdentifierField.h:136
DeMoScan.index
string index
Definition: DeMoScan.py:364
InDetDD::other
@ other
Definition: InDetDD_Defs.h:16
IdentifierField::operator|=
void operator|=(const IdentifierField &other)
Definition: IdentifierField.cxx:319
IdentifierField::m_indexes
index_vector m_indexes
Definition: IdentifierField.h:132
IdentifierField
This is the individual specification for the range of one ExpandedIdentifier IdentifierField.
Definition: IdentifierField.h:21
IdentifierField::BoundedRange
std::pair< element_type, element_type > BoundedRange
Definition: IdentifierField.h:27
IdentifierField::has_next
@ has_next
Definition: IdentifierField.h:34
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
IdentifierField::get_previous
bool get_previous(element_type current, element_type &previous) const
Returns false if previous/next is at end of range, or not possible.
Definition: IdentifierField.cxx:106
IdentifierField::has_previous
@ has_previous
Definition: IdentifierField.h:35
IdentifierField::show
void show() const
Definition: IdentifierField.cxx:376
IdentifierField::optimize
void optimize()
Optimize - try to switch mode to both_bounded, set up lookup table for finding index from value.
Definition: IdentifierField.cxx:422
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
python.compressB64.c
def c
Definition: compressB64.py:93
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
IdentifierField::add_value
void add_value(element_type value)
Definition: IdentifierField.cxx:250
Trk::previous
@ previous
Definition: BinningData.h:32
IdentifierField::IdentifierField
IdentifierField()=default
Create a wild-card value.
Identifier
Definition: IdentifierFieldParser.cxx:14