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