ATLAS Offline Software
Loading...
Searching...
No Matches
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//-----------------------------------------------
37Range::Range (const Range& other, size_type start) {
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
45Range::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//-----------------------------------------------
58void Range::build (const std::string& text) {
59 if (text.empty()) return;
60 std::istringstream in(text);
61 in>>*this;
62}
63
64//-----------------------------------------------
65void Range::build (const ExpandedIdentifier& root) {
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
74
75//-----------------------------------------------
76void Range::add (element_type value) {
77 m_fields.emplace_back (value);
78}
79
80//-----------------------------------------------
84
85
86
88void Range::add (const field& f) {
89 m_fields.emplace_back(f);
90}
91
93void Range::add (field&& f) {
94 m_fields.emplace_back(std::move(f));
95}
96
98void Range::add (const Range& subrange) {
99 for (size_t i = 0; i < subrange.fields (); ++i) {
100 const field& f = subrange[i];
101 m_fields.push_back (f);
102 }
103}
104
105void Range::add (Range&& subrange) {
106 if (m_fields.empty())
107 m_fields.swap (subrange.m_fields);
108 else {
109 size_t sz = subrange.m_fields.size();
110 m_fields.reserve (m_fields.size() + sz);
111 for (size_t i = 0; i < sz; ++i) {
112 m_fields.emplace_back (std::move(subrange.m_fields[i]));
113 }
114 }
115}
116
117
118
119
120//-----------------------------------------------
121void Range::clear () {
122 m_fields.clear ();
123}
124
125//-----------------------------------------------
126int Range::match (const ExpandedIdentifier& id) const {
127
128 size_type my_fields = m_fields.size ();
129 const size_type id_fields = id.fields ();
130
131 // More fields in the range than in the identifier will never match.
132 //if (my_fields > id_fields) return (0);
133
134 // Allow match for id shorter than range - assume "wildcards" for
135 // missing id fields
136 size_type nfields = (my_fields > id_fields) ? id_fields : my_fields;
137 // Test fields one by one.
138 for (size_type field_number = 0; field_number < nfields; field_number++) {
139 const field& f = m_fields[field_number];
140 if (!f.match (id[field_number])) return (0);
141 }
142 // All conditions match.
143 return (1);
144}
145
146// Accessors
147
148//-----------------------------------------------
150 size_type my_fields = m_fields.size ();
152 // Copy fields to result
153 for (size_type field_number = 0; field_number < my_fields; field_number++) {
154 const field& f = m_fields[field_number];
155 // Valued field
156 result << f.get_minimum ();
157 }
158 return (result);
159}
160
161//-----------------------------------------------
163 size_type my_fields = m_fields.size ();
165 // Copy fields to result
166 for (size_type field_number = 0; field_number < my_fields; field_number++) {
167 const field& f = m_fields[field_number];
168 // Normal field
169 result << f.get_maximum ();
170 }
171 return (result);
172}
173
175 size_type result = 1;
176 const Range& me = *this;
177 for (size_type i = 0; i < fields (); ++i) {
178 const field& f = me[i];
179 result *= f.get_indices ();
180 }
181 return (result);
182}
183
184
189 size_type result = 0;
190 if (id.fields() != fields()) return (result);
191 const Range& me = *this;
192 // Check if we are above or below this range
193 if (id < minimum()) return 0;
194 if (maximum() < id) return cardinality();
195 // Collect the indices of a match
196 std::vector<size_type> indices(id.fields (), 0);
197 bool is_match = true;
198 size_type level = 0;
199 for (; level < id.fields (); ++level) {
200 const field& f = me[level];
201 // Require all fields to be bounded or enumerated
202 if (f.empty()) return 0;
203 if (f.isEnumerated()) {
204 // Continue testing for a match
205 size_type max = f.get_values().size() - 1;
206 if (f.get_values()[max] < id[level]) {
207 // above max
208 is_match = false;
209 indices[level] = max + 1;
210 } else {
211 for (size_type j = 0; j < f.get_values().size(); ++j) {
212 if (id[level] <= f.get_values()[j]) {
213 if (id[level] != f.get_values()[j]) {
214 // between two values or below first one
215 is_match = false;
216 }
217 indices[level] = j;
218 break;
219 }
220 }
221 }
222 } else {
223 if (f.get_maximum() < id[level]) {
224 // above max
225 is_match = false;
226 indices[level] = f.get_maximum() - f.get_minimum() + 1;
227 } else if (id[level] < f.get_minimum()) {
228 // below min
229 is_match = false;
230 indices[level] = 0;
231 } else {
232 indices[level] = id[level] - f.get_minimum();
233 }
234 }
235 if (!is_match) break;
236 }
237
238 // Calculate the cardinality
239 if (level < id.fields ()) ++level;
240 for (size_type j = 0; j < level; ++j) {
241 size_type card = indices[j];
242 for (size_type k = j + 1; k < id.fields(); ++k) {
243 const field& f = me[k];
244 card *= f.get_indices();
245 }
246 result += card;
247 }
248 return result;
249}
250
251
258bool Range::overlaps_with (const Range& other) const {
259 const Range& me = *this;
260 if ((fields () == 0) || (other.fields () == 0)) return (false);
261 for (size_type i = 0; i < std::min (fields (), other.fields ()); ++i){
262 const field& f1 = me[i];
263 const field& f2 = other[i];
264 if (!f1.overlaps_with (f2)) return (false);
265 }
266 return (true);
267}
268
269//-----------------------------------------------
270void Range::show () const {
271 show (std::cout);
272}
273
274void Range::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
297//-----------------------------------------------
298Range::operator std::string () const {
299 std::string result;
300 size_type my_fields = m_fields.size ();
301 if (my_fields == 0) return (result);
302 // print fields one by one.
303 for (size_type field_number = 0; field_number < my_fields; field_number++) {
304 const field& f = m_fields[field_number];
305 if (field_number > 0) result += "/";
306 result += (std::string) f;
307 }
308 return (result);
309}
310
311//-----------------------------------------------
312bool
313Range::operator == (const Range& other) const{
314 if (m_fields.size() != other.m_fields.size()) return false;
315 field_vector::const_iterator it1 = m_fields.begin();
316 field_vector::const_iterator it2 = other.m_fields.begin();
317 field_vector::const_iterator last = m_fields.end();
318 for (; it1 != last; ++it1, ++it2) {
319 if ((*it1) != (*it2)) return false;
320 }
321 return (true);
322}
323
324
325
326
327
328
329std::ostream &
330operator << (std::ostream &out, const Range &r){
331 out<<std::string(r);
332 return out;
333}
334
335std::istream &
336operator >> (std::istream &in, Range &r){
337 r.clear ();
338 for (int c{}; c!=EOF;c=in.peek()){
339 Range::field field;
340 in>>field;
341 r.add(field);
342 if (int c = in.peek();(c == '/') or (c ==' ')){
343 in.ignore();
344 }
345 }
346 return in;
347}
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 :
int r
Definition globals.cxx:22
Definition index.py:1