ATLAS Offline Software
Loading...
Searching...
No Matches
DetectorDescription/Identifier/src/Range.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 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
15#include "GaudiKernel/MsgStream.h"
16#include <algorithm>
17#include <cstdio>
18#include <string>
19#include <vector>
20#include <sstream>
21#include <limits>
22#include <iomanip>
23#include <stdexcept>
24#include <cassert>
25
26
27
28//--------------------------------------------------------------------------
30 if (index >= m_fields.size ()){
31 static const field f;
32 return (f);
33 }
34 return (m_fields[index]);
35}
36
37//-----------------------------------------------
38Range::Range (const Range& other, size_type start) {
39 if (start < other.fields ()) {
40 field_vector::const_iterator it = other.m_fields.begin ();
41 it += start;
42 m_fields.insert (m_fields.end (), it, other.m_fields.end ());
43 }
44}
45
46Range::Range(const std::string & text):Range(){
47 if (text.empty()) return;
48 std::istringstream in(text);
49 in>>*this;
50}
51
52//-----------------------------------------------
54 // Construct from a root (i.e. add wild card for below)
55 build (root);
56}
57
58//-----------------------------------------------
59void Range::build (const std::string& text) {
60 if (text.empty()) return;
61 std::istringstream in(text);
62 in>>*this;
63}
64
65//-----------------------------------------------
66void Range::build (const ExpandedIdentifier& root) {
67 // Construct from a root
68 m_fields.clear ();
69 for (size_type i = 0; i < root.fields (); ++i){
70 m_fields.emplace_back(root[i]);
71 }
72}
73
74
75
76//-----------------------------------------------
77void Range::add (element_type value) {
78 m_fields.emplace_back (value);
79}
80
81//-----------------------------------------------
85
86
87
89void Range::add (const field& f) {
90 m_fields.emplace_back(f);
91}
92
94void Range::add (field&& f) {
95 m_fields.emplace_back(std::move(f));
96}
97
99void Range::add (const Range& subrange) {
100 for (size_t i = 0; i < subrange.fields (); ++i) {
101 const field& f = subrange[i];
102 m_fields.push_back (f);
103 }
104}
105
106void Range::add (Range&& subrange) {
107 if (m_fields.empty())
108 m_fields.swap (subrange.m_fields);
109 else {
110 size_t sz = subrange.m_fields.size();
111 m_fields.reserve (m_fields.size() + sz);
112 for (size_t i = 0; i < sz; ++i) {
113 m_fields.emplace_back (std::move(subrange.m_fields[i]));
114 }
115 }
116}
117
118
119
120
121//-----------------------------------------------
122void Range::clear () {
123 m_fields.clear ();
124}
125
126//-----------------------------------------------
127int Range::match (const ExpandedIdentifier& id) const {
128
129 size_type my_fields = m_fields.size ();
130 const size_type id_fields = id.fields ();
131
132 // More fields in the range than in the identifier will never match.
133 //if (my_fields > id_fields) return (0);
134
135 // Allow match for id shorter than range - assume "wildcards" for
136 // missing id fields
137 size_type nfields = (my_fields > id_fields) ? id_fields : my_fields;
138 // Test fields one by one.
139 for (size_type field_number = 0; field_number < nfields; field_number++) {
140 const field& f = m_fields[field_number];
141 if (!f.match (id[field_number])) return (0);
142 }
143 // All conditions match.
144 return (1);
145}
146
147// Accessors
148
149//-----------------------------------------------
151 size_type my_fields = m_fields.size ();
153 // Copy fields to result
154 for (size_type field_number = 0; field_number < my_fields; field_number++) {
155 const field& f = m_fields[field_number];
156 // Valued field
157 result << f.get_minimum ();
158 }
159 return (result);
160}
161
162//-----------------------------------------------
164 size_type my_fields = m_fields.size ();
166 // Copy fields to result
167 for (size_type field_number = 0; field_number < my_fields; field_number++) {
168 const field& f = m_fields[field_number];
169 // Normal field
170 result << f.get_maximum ();
171 }
172 return (result);
173}
174
176 size_type result = 1;
177 const Range& me = *this;
178 for (size_type i = 0; i < fields (); ++i) {
179 const field& f = me[i];
180 result *= f.get_indices ();
181 }
182 return (result);
183}
184
185
190 size_type result = 0;
191 if (id.fields() != fields()) return (result);
192 const Range& me = *this;
193 // Check if we are above or below this range
194 if (id < minimum()) return 0;
195 if (maximum() < id) return cardinality();
196 // Collect the indices of a match
197 std::vector<size_type> indices(id.fields (), 0);
198 bool is_match = true;
199 size_type level = 0;
200 for (; level < id.fields (); ++level) {
201 const field& f = me[level];
202 // Require all fields to be bounded or enumerated
203 if (f.empty()) return 0;
204 if (f.isEnumerated()) {
205 // Continue testing for a match
206 size_type max = f.get_values().size() - 1;
207 if (f.get_values()[max] < id[level]) {
208 // above max
209 is_match = false;
210 indices[level] = max + 1;
211 } else {
212 for (size_type j = 0; j < f.get_values().size(); ++j) {
213 if (id[level] <= f.get_values()[j]) {
214 if (id[level] != f.get_values()[j]) {
215 // between two values or below first one
216 is_match = false;
217 }
218 indices[level] = j;
219 break;
220 }
221 }
222 }
223 } else {
224 if (f.get_maximum() < id[level]) {
225 // above max
226 is_match = false;
227 indices[level] = f.get_maximum() - f.get_minimum() + 1;
228 } else if (id[level] < f.get_minimum()) {
229 // below min
230 is_match = false;
231 indices[level] = 0;
232 } else {
233 indices[level] = id[level] - f.get_minimum();
234 }
235 }
236 if (!is_match) break;
237 }
238
239 // Calculate the cardinality
240 if (level < id.fields ()) ++level;
241 for (size_type j = 0; j < level; ++j) {
242 size_type card = indices[j];
243 for (size_type k = j + 1; k < id.fields(); ++k) {
244 const field& f = me[k];
245 card *= f.get_indices();
246 }
247 result += card;
248 }
249 return result;
250}
251
252
259bool Range::overlaps_with (const Range& other) const {
260 const Range& me = *this;
261 if ((fields () == 0) || (other.fields () == 0)) return (false);
262 for (size_type i = 0; i < std::min (fields (), other.fields ()); ++i){
263 const field& f1 = me[i];
264 const field& f2 = other[i];
265 if (!f1.overlaps_with (f2)) return (false);
266 }
267 return (true);
268}
269
270
271
272void
273Range::show (std::ostream& s) const {
274 const Range& me = *this;
275 s << (std::string) me << " (";
276 int allbits = 0;
277 for (size_type i = 0; i < fields (); ++i) {
278 const field& f = me[i];
279 if (i > 0) s << "+";
280 size_type indices = f.get_indices ();
281 int bits = 1;
282 indices--;
283 if (indices > 0) {
284 bits = 0;
285 while (indices > 0){
286 indices /= 2;
287 bits++;
288 }
289 }
290 allbits += bits;
291 s << bits;
292 }
293 s << "=" << allbits << ") ";
294}
295
296void
297Range::show (MsgStream & out) const{
298 std::ostringstream os;
299 show(os);
300 out << os.str();
301}
302
303//-----------------------------------------------
304Range::operator std::string () const {
305 std::string result;
306 size_type my_fields = m_fields.size ();
307 if (my_fields == 0) return (result);
308 // print fields one by one.
309 for (size_type field_number = 0; field_number < my_fields; field_number++) {
310 const field& f = m_fields[field_number];
311 if (field_number > 0) result += "/";
312 result += (std::string) f;
313 }
314 return (result);
315}
316
317//-----------------------------------------------
318bool
319Range::operator == (const Range& other) const{
320 if (m_fields.size() != other.m_fields.size()) return false;
321 field_vector::const_iterator it1 = m_fields.begin();
322 field_vector::const_iterator it2 = other.m_fields.begin();
323 field_vector::const_iterator last = m_fields.end();
324 for (; it1 != last; ++it1, ++it2) {
325 if ((*it1) != (*it2)) return false;
326 }
327 return (true);
328}
329
330
331
332
333
334
335std::ostream &
336operator << (std::ostream &out, const Range &r){
337 out<<std::string(r);
338 return out;
339}
340
341std::istream &
342operator >> (std::istream &in, Range &r){
343 r.clear ();
344 for (int c{}; c!=EOF;c=in.peek()){
345 Range::field field;
346 in>>field;
347 r.add(field);
348 if (int c = in.peek();(c == '/') or (c ==' ')){
349 in.ignore();
350 }
351 }
352 return in;
353}
std::ostream & operator<<(std::ostream &out, const Range &r)
std::istream & operator>>(std::istream &in, Range &r)
static Double_t sz
#define max(a, b)
Definition cfImp.cxx:41
A Range describes the possible ranges for the field values of an ExpandedIdentifier.
ExpandedIdentifier maximum() const
int match(const ExpandedIdentifier &id) const
Match an identifier.
Range()=default
ExpandedIdentifier minimum() const
min and max ExpandedIdentifiers (if they exist, ie.
bool operator==(const Range &other) const
void add(element_type value)
Add a required value. (ie. low = high = value)
ExpandedIdentifier::element_type element_type
size_type cardinalityUpTo(const ExpandedIdentifier &id) const
Get the cardinality from the beginning up to the given ExpandedIdentifier.
ExpandedIdentifier::size_type size_type
void build(const std::string &text)
Build Range from a textual description.
const field & operator[](size_type index) const
Access the field elements.
bool overlaps_with(const Range &other) const
Check if two Ranges overlap.
size_type cardinality() const
Computes a possible cardinality :
void show(std::ostream &s=std::cout) const
int r
Definition globals.cxx:22
Definition index.py:1