ATLAS Offline Software
Loading...
Searching...
No Matches
IdentifierField Class Reference

This is the individual specification for the range of one ExpandedIdentifier IdentifierField. More...

#include <IdentifierField.h>

Collaboration diagram for IdentifierField:

Public Types

enum  continuation_mode {
  none , has_next , has_previous , has_both ,
  has_wrap_around
}
using element_type = ExpandedIdentifier::element_type
using size_type = ExpandedIdentifier::size_type
using element_vector = std::vector <element_type>
using index_vector = std::vector <size_type>
using BoundedRange = std::pair<element_type, element_type>

Public Member Functions

 IdentifierField ()=default
 Create a wild-card value.
 IdentifierField (element_type value)
 Create a unique value (understood as : low bound = high bound = value)
 IdentifierField (element_type minimum, element_type maximum)
 Create a full range specification (with explicit min and max)
 IdentifierField (const element_vector &values)
 Create with enumerated values.
bool wrap_around () const
element_type get_minimum () const
 Query the values.
std::pair< element_type, element_typeget_minmax () const
element_type get_maximum () const
const element_vectorget_values () const
bool get_previous (element_type current, element_type &previous) const
 Returns false if previous/next is at end of range, or not possible.
bool get_next (element_type current, element_type &next) const
size_type get_indices () const
const index_vectorget_indexes () const
size_type get_bits () const
 Return the number of bits needed to store a value of this field.
element_type get_value_at (size_type index) const
size_type get_value_index (element_type value) const
bool match (element_type value) const
 The basic match operation Given a value, test to see if it satisfies the constraints for this field.
bool overlaps_with (const IdentifierField &other) const
 Check whether two IdentifierFields overlap (Are there any values which satisfy the constraints of both fields?)
void clear ()
 Set methods.
void set (element_type minimum, element_type maximum)
void add_value (element_type value)
void set (const element_vector &values)
void set (bool wraparound)
void set_next (int next)
void set_previous (int previous)
void operator|= (const IdentifierField &other)
 Find the union of two fields.
 operator std::string () const
bool operator== (const IdentifierField &other) const
void show (std::ostream &out=std::cout) const
void show (MsgStream &out) const
bool check_for_both_bounded ()
 Check mode - switch from enumerated to both_bounded if possible.
void optimize ()
 Optimize - try to switch mode to both_bounded, set up lookup table for finding index from value.
bool empty () const
 If true, this field does not have any constraints, and may hold any value representable by element_type.
bool isBounded () const
bool isEnumerated () const

Static Public Attributes

static constexpr auto minimum_possible = std::numeric_limits<element_type>::min()
static constexpr auto maximum_possible = std::numeric_limits<element_type>::max()
static constexpr auto invalidValues = element_vector{}

Private Member Functions

void set_minimum (element_type value)
void set_maximum (element_type value)
void create_index_table ()
 Create index table from value table.
template<class T>
T * dataPtr ()

Private Attributes

element_type m_minimum {}
element_type m_maximum {}
std::variant< element_vector, BoundedRangem_data {}
index_vector m_indexes {}
size_type m_size {}
element_type m_previous {}
element_type m_next {}
bool m_empty {true}
continuation_mode m_continuation_mode {none}

Static Private Attributes

static constexpr int m_maxNumberOfIndices = 100

Detailed Description

This is the individual specification for the range of one ExpandedIdentifier IdentifierField.

A field specifies a constraint on the values it may contain. This may take one of three forms:

  • Completely unconstrained. In this case, empty() will return true, implying that the field may hold any value representable by element_type. (Yes, it's a bad name and means the opposite of what you may think...) An empty field is made by the default constructor, and also by calling clear().
  • A bounded (inclusive) range. In this case, isBounded() will return true, get_maximum/get_minimum will return the ends of the range, and get_indices() will return the number of values in the range (maximum - minimum + 1). A bounded field may be made by calling the constructor with a minimum and maximum, or by calling set() with the same arguments. The range is also stored in m_data as the BoundedRange option.
  • An enumeration. In this case, isEnumerated() will return true, get_maximum/get_minimum will return the minimum and maximum enumeration values, and get_indices() will return the number of enumeration values. get_values() will return a (sorted) vector of all the values. An enumerated field may be made by passing a vector to the constructor or set(), or by calling add_value() with individual values. The values are stored in m_data as the element_vector option.

Each valid value is assigned an index, starting with 0. For bounded ranges, this just starts from the minimum value and counts up. For enumerations, it is the index of that particular enumeration value. You can convert between values and indices using get_value_at() and get_value_index(). For value->index conversions, a lookup table is used if optimize() has been called and the spread of values is not too large. get_indices() will return this table.

As far as users of this class see, there is not really a distinction between a dense enumeration and a bounded range. In fact, check_for_both_bounded()/optimize() will convert a dense enumeration to a bounded range.

Given a value, one can ask for the next/previous valid value using get_next()/get_previous(). For an enumeration, this will return the next or previous enumeration value. If you try to call get_next() for the maximum value in the range, or get_previous() from the minimum, then they will by default fail (return false). This can be changed by calling set_next()/set_previous() to specify explictly values to be returned in these cases, or by calling set(true) to enable wraparound mode; in that case, calling get_next() for the maximum value will return the minimum value, and analogously for get_previous().

Other operations include:

  • get_bits(): Return the number of bits needed to store a value of this field.

match(): Given a value, test whether it satisfies the constraints for this field.

  • overlaps_with(): Test to see if there are any values which satisfy the constraints of both fields.
  • operator|=(): Find the union of two fields. Note: does not correctly handle the cases of an enumeration and a bounded range or two disjoint bounded ranges! If either is empty (meaning no constraint), then the result will be empty.
    • operator==(): Test if two fields have identical constraints. However, a dense enumeration will not compare identically to an equivalent bounded range.

Definition at line 84 of file IdentifierField.h.

Member Typedef Documentation

◆ BoundedRange

Definition at line 91 of file IdentifierField.h.

◆ element_type

◆ element_vector

Definition at line 89 of file IdentifierField.h.

◆ index_vector

Definition at line 90 of file IdentifierField.h.

◆ size_type

Member Enumeration Documentation

◆ continuation_mode

Enumerator
none 
has_next 
has_previous 
has_both 
has_wrap_around 

Definition at line 96 of file IdentifierField.h.

Constructor & Destructor Documentation

◆ IdentifierField() [1/4]

IdentifierField::IdentifierField ( )
default

Create a wild-card value.

◆ IdentifierField() [2/4]

IdentifierField::IdentifierField ( element_type value)

Create a unique value (understood as : low bound = high bound = value)

Definition at line 84 of file IdentifierField.cxx.

85 :
86 m_minimum(value),
87 m_maximum(value),
89 m_empty{false}{
90 //
91}
std::pair< element_type, element_type > BoundedRange
element_type m_maximum
element_type m_minimum
std::variant< element_vector, BoundedRange > m_data

◆ IdentifierField() [3/4]

IdentifierField::IdentifierField ( element_type minimum,
element_type maximum )

Create a full range specification (with explicit min and max)

Definition at line 94 of file IdentifierField.cxx.

94 {
95 set(minimum, maximum);
96}
void set(element_type minimum, element_type maximum)

◆ IdentifierField() [4/4]

IdentifierField::IdentifierField ( const element_vector & values)

Create with enumerated values.

Definition at line 100 of file IdentifierField.cxx.

100 {
101 set(values);
102}

Member Function Documentation

◆ add_value()

void IdentifierField::add_value ( element_type value)

Definition at line 251 of file IdentifierField.cxx.

251 {
252 if (auto * p = dataPtr<element_vector>(); !p) {
253 clear();
254 m_data = element_vector(1,value);//now its enumerated
255 m_size = 1;
256 } else {
257 //check whether value already exists in the enumeration vector
258 if (std::ranges::binary_search(*p, value)) return;
259 p->push_back(value);
260 std::ranges::sort(*p);
261 m_size = p->size();
262 }
263 m_minimum = get_values().front();
264 m_maximum = get_values().back();
265 m_empty = false;
266}
void clear()
Set methods.
std::vector< element_type > element_vector
const element_vector & get_values() const

◆ check_for_both_bounded()

bool IdentifierField::check_for_both_bounded ( )

Check mode - switch from enumerated to both_bounded if possible.

Definition at line 444 of file IdentifierField.cxx.

444 {
445 if (m_empty) return false;
446 if (isEnumerated()) {
447 //the enumerated values are kept sorted
448 if (m_size-1 == static_cast<size_type>(m_maximum - m_minimum)){
450 return true;
451 }
452 }
453 return false;
454}
ExpandedIdentifier::size_type size_type
bool isEnumerated() const

◆ clear()

void IdentifierField::clear ( )

Set methods.

Definition at line 225 of file IdentifierField.cxx.

225 {
226 m_minimum = 0;
227 m_maximum = 0;
228 m_previous = 0;
229 m_next = 0;
232 m_indexes.clear();
233 m_empty = true;
234}
element_type m_next
index_vector m_indexes
element_type m_previous
continuation_mode m_continuation_mode

◆ create_index_table()

void IdentifierField::create_index_table ( )
private

Create index table from value table.

Create index table from value table

Definition at line 458 of file IdentifierField.cxx.

458 {
459 if (m_empty) return;
461 if (isEnumerated()) {
462 size_type size = m_maximum - m_minimum + 1;
463 // return if we are over the maximum desired vector table size
464 if (size > m_maxNumberOfIndices) {
465 m_indexes.clear();
466 return;
467 }
468 // Set up vectors for decoding
469 m_indexes = std::vector<size_type>(size, 0);
471 int i{};
472 auto &v = std::get<element_vector>(m_data);
473 for (const auto & thisValue: v) {
474 if (const auto idx=(thisValue - m_minimum); idx < (int)size) {
476 index++;
477 } else {
478 std::cout << "size, value, index, i "
479 << size << " " << thisValue << " "
480 << index << " " << i++ << " min, max "
481 << m_minimum << " "
482 << m_maximum
483 << std::endl;
484 }
485 }
486 }
487}
static constexpr int m_maxNumberOfIndices
str index
Definition DeMoScan.py:362

◆ dataPtr()

template<class T>
T * IdentifierField::dataPtr ( )
inlineprivate

Definition at line 198 of file IdentifierField.h.

198{return std::get_if<T>(&m_data);}

◆ empty()

bool IdentifierField::empty ( ) const
inline

If true, this field does not have any constraints, and may hold any value representable by element_type.

Definition at line 185 of file IdentifierField.h.

185{return m_empty;}

◆ get_bits()

ExpandedIdentifier::size_type IdentifierField::get_bits ( ) const

Return the number of bits needed to store a value of this field.

Definition at line 41 of file IdentifierField.cxx.

41 {
42 size_t indices = get_indices ();
43 if (--indices) return std::bit_width(indices);
44 return 1;
45}
size_type get_indices() const
std::pair< long int, long int > indices

◆ get_indexes()

const index_vector & IdentifierField::get_indexes ( ) const
inline

Definition at line 143 of file IdentifierField.h.

143{return m_indexes;}

◆ get_indices()

size_type IdentifierField::get_indices ( ) const
inline

Definition at line 142 of file IdentifierField.h.

142{return m_size;}

◆ get_maximum()

element_type IdentifierField::get_maximum ( ) const
inline

Definition at line 132 of file IdentifierField.h.

132{return m_maximum;}

◆ get_minimum()

element_type IdentifierField::get_minimum ( ) const
inline

Query the values.

Definition at line 123 of file IdentifierField.h.

123{return m_minimum;}

◆ get_minmax()

std::pair< element_type, element_type > IdentifierField::get_minmax ( ) const
inline

Definition at line 127 of file IdentifierField.h.

127 {
128 return {m_minimum, m_maximum};
129 }

◆ get_next()

bool IdentifierField::get_next ( element_type current,
element_type & next ) const

Definition at line 150 of file IdentifierField.cxx.

150 {
151 if (m_empty){
152 next = current + 1;
153 return (current != maximum_possible);
154 }
155
156 if (isBounded()){
157 if (current == m_maximum) {
159 next = m_minimum;
160 return (true);
161 }
163 next = m_next;
164 return (true);
165 }
166 next = current;
167 return (false);
168 }
169 next = current + 1;
170 return (true);
171 }
172 const auto & values= get_values();
174 if ((index == values.size() - 1) || (index == 0 && current != values.front())) {
176 next = values.front();
177 return (true);
178 }
180 next = m_next;
181 return (true);
182 }
183 next = current;
184 return (false);
185 }
186 ++index;
187 next = values[index];
188 return true;
189}
static constexpr auto maximum_possible
size_type get_value_index(element_type value) const
bool isBounded() const

◆ get_previous()

bool IdentifierField::get_previous ( element_type current,
element_type & previous ) const

Returns false if previous/next is at end of range, or not possible.

Definition at line 107 of file IdentifierField.cxx.

107 {
108 if (m_empty){
109 previous = current - 1;
110 return (current != minimum_possible);
111 }
112 if (isBounded()){
113 if (current == m_minimum) {
116 return (true);
117 }
120 return (true);
121 }
123 return (false);
124 }
125 previous = current - 1;
126 return (true);
127 }
128 const auto & values= get_values();
130 if (index == 0) {
132 previous = values.back();
133 return (true);
134 }
137 return (true);
138 }
140 return (false);
141 }
142 --index;
144 return true;
145}
static constexpr auto minimum_possible
@ previous
Definition BinningData.h:32

◆ get_value_at()

IdentifierField::element_type IdentifierField::get_value_at ( size_type index) const
inline

Definition at line 212 of file IdentifierField.h.

212 {
213 // Only both_bounded and enumerated are valid to calculate the
214 // value.
215 // both_bounded is the more frequent case and so comes first.
216 if (m_empty) return 0;
217 if (const auto * p{std::get_if<BoundedRange>(&m_data)}; p) {
218 if (index >= (size_type) (p->second - p->first + 1)) {
219 throw std::out_of_range("IdentifierField::get_value_at");
220 }
221 return (p->first + index);
222 }
223 return ((std::get<element_vector>(m_data)).at(index));
224
225}

◆ get_value_index()

ExpandedIdentifier::size_type IdentifierField::get_value_index ( element_type value) const

Definition at line 50 of file IdentifierField.cxx.

50 {
51 // Only both_bounded and enumerated are valid to calculate the
52 // index.
53 // both_bounded if the more frequent case and so comes first.
54 if (isBounded()) {
55 return (value - m_minimum);
56 }
57 const auto & v = get_values();
58 if (v.size()==1) return 0;
59 if (not m_indexes.empty()) {
60 // Table has been created, do simple lookup
61 assert (value >= m_minimum && value - m_minimum < (int)m_indexes.size());
62 return (m_indexes.at(value - m_minimum));
63 } else {
64 auto it = std::ranges::find(v, value);
65 if (it != v.end()) return std::distance(v.begin(), it);
66 }
67 return 0;
68}

◆ get_values()

const element_vector & IdentifierField::get_values ( ) const
inline

Definition at line 135 of file IdentifierField.h.

135 {
136 if (isBounded()) return invalidValues;
137 return std::get<element_vector>(m_data);
138 }
static constexpr auto invalidValues

◆ isBounded()

bool IdentifierField::isBounded ( ) const
inline

Definition at line 187 of file IdentifierField.h.

187{return std::holds_alternative<BoundedRange>(m_data);}

◆ isEnumerated()

bool IdentifierField::isEnumerated ( ) const
inline

Definition at line 188 of file IdentifierField.h.

188{return std::holds_alternative<element_vector>(m_data);}

◆ match()

bool IdentifierField::match ( element_type value) const

The basic match operation Given a value, test to see if it satisfies the constraints for this field.

Definition at line 72 of file IdentifierField.cxx.

72 {
73 if (isBounded()) {
74 return ((value >= m_minimum) && (value <= m_maximum));
75 }
76 if (m_empty) return true;
77 const auto & v = get_values();
78 return (std::ranges::find(v, value)!=v.end());
79}

◆ operator std::string()

IdentifierField::operator std::string ( ) const

Definition at line 344 of file IdentifierField.cxx.

344 {
345 std::string result;
346 if (m_empty) {
347 result = "*";
348 } else {
349 const auto & [minimum, maximum] = get_minmax();
350 if (minimum == maximum) {
351 result = std::to_string(minimum);
352 } else {
353 if (isEnumerated()) {
354 std::string prefix;
355 for (size_type i = 0; i < get_indices (); ++i) {
356 result += prefix+std::to_string(get_value_at(i));
357 prefix = ",";
358 }
359 } else {
360 try {
361 result = std::format("{}:{}", minimum, maximum);
362 }
363 catch (const std::format_error& e) {
364 result = "ERROR ";
365 result += e.what();
366 }
367 }
368 }
369 }
370 return result;
371}
std::pair< element_type, element_type > get_minmax() const
element_type get_value_at(size_type index) const

◆ operator==()

bool IdentifierField::operator== ( const IdentifierField & other) const

Definition at line 375 of file IdentifierField.cxx.

375 {
376 if (m_data != other.m_data) return false;
377 return (true);
378}

◆ operator|=()

void IdentifierField::operator|= ( const IdentifierField & other)

Find the union of two fields.

Note: does not correctly handle the cases of an enumeration and a bounded range or two disjoint bounded ranges! If either is empty (meaning no constraint), then the result will be empty.

If there is no overlap we should build a multi-segment specification. The current algorithm is only correct if the overlap in not empty !! A multi-segment specification might also be implemented as an expanded enumerated set (not very optimized !!)

Definition at line 320 of file IdentifierField.cxx.

320 {
321 if (m_empty or other.m_empty){
322 clear();
323 m_size = 1;
324 return;
325 }
326 if (isEnumerated() and other.isEnumerated()){
327 set(other.get_values ());
328 return;
329 }
336 // all other cases...
337 const auto min = std::min(m_minimum, other.m_minimum);
338 const auto max = std::max(m_maximum, other.m_maximum);
339 set(min, max);
340}
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41

◆ optimize()

void IdentifierField::optimize ( )

Optimize - try to switch mode to both_bounded, set up lookup table for finding index from value.

Check mode - switch from enumerated to both_bounded if possible

Definition at line 436 of file IdentifierField.cxx.

436 {
439}
bool check_for_both_bounded()
Check mode - switch from enumerated to both_bounded if possible.
void create_index_table()
Create index table from value table.

◆ overlaps_with()

bool IdentifierField::overlaps_with ( const IdentifierField & other) const

Check whether two IdentifierFields overlap (Are there any values which satisfy the constraints of both fields?)

Definition at line 195 of file IdentifierField.cxx.

195 {
196 if (m_empty or other.m_empty) return true;
197 //
198 if (isBounded() and other.isBounded()){
199 return ((m_minimum <= other.m_maximum) && (m_maximum >= other.m_minimum));
200 }
201 //
202 if (isBounded() and other.isEnumerated() ){
203 const element_vector& ev = other.get_values();
204 for (const auto & v: ev) {
205 if (v >= m_minimum and v<= m_maximum) return (true);
206 }
207 return false;
208 } else if (isEnumerated() and other.isBounded()){
209 const element_vector& ev = get_values();
210 for (const auto & v: ev){
211 if ((v >= other.m_minimum) and (v <= other.m_maximum)) return (true);
212 }
213 return false;
214 }
215 // Both fields are enumerated only if there is possibility of overlap
216 if ((m_minimum <= other.m_maximum) && (m_maximum >= other.m_minimum)) {
217 return share_element(get_values(), other.get_values());
218 }
219 return (false);
220}
int ev
Definition globals.cxx:25

◆ set() [1/3]

void IdentifierField::set ( bool wraparound)

Definition at line 288 of file IdentifierField.cxx.

288 {
289 if (wraparound) {
291 }
292}

◆ set() [2/3]

void IdentifierField::set ( const element_vector & values)

◆ set() [3/3]

void IdentifierField::set ( element_type minimum,
element_type maximum )

Definition at line 238 of file IdentifierField.cxx.

238 {
239 if (minimum == maximum) {
240 add_value(minimum);
241 } else {
242 std::tie(m_minimum,m_maximum) = std::minmax(minimum,maximum);
244 m_size = m_maximum - m_minimum + 1;
245 }
246 m_empty=false;
247}
void add_value(element_type value)

◆ set_maximum()

void IdentifierField::set_maximum ( element_type value)
private

◆ set_minimum()

void IdentifierField::set_minimum ( element_type value)
private

◆ set_next()

void IdentifierField::set_next ( int next)

Definition at line 296 of file IdentifierField.cxx.

296 {
299 } else {
301 }
302 m_next = next;
303}

◆ set_previous()

void IdentifierField::set_previous ( int previous)

Definition at line 308 of file IdentifierField.cxx.

308 {
311 } else {
313 }
315}

◆ show() [1/2]

void IdentifierField::show ( MsgStream & out) const

Definition at line 426 of file IdentifierField.cxx.

426 {
427 std::ostringstream os;
428 show(os);
429 out << os.str();
430}
void show(std::ostream &out=std::cout) const

◆ show() [2/2]

void IdentifierField::show ( std::ostream & out = std::cout) const

Definition at line 383 of file IdentifierField.cxx.

383 {
384 out << "min/max " << m_minimum << " " << m_maximum << " ";
385 out << "values ";
386 for (const auto& v: get_values()) {
387 out << v << " ";
388 }
389 out << "indexes ";
390 for (const auto & idx: m_indexes) {
391 out << idx << " ";
392 }
393 out << "indices " << m_size << " ";
394 out << "prev " << m_previous << " ";
395 out << "next " << m_next << " ";
396 out << "mode ";
397 if (m_empty){
398 out << "unbounded ";
399 }else if (isBounded()){
400 out << "both_bounded ";
401 }else if (isEnumerated()) {
402 out << "enumerated ";
403 }
404 out << "cont mode ";
405 switch (m_continuation_mode) {
407 out << "none ";
408 break;
410 out << "has_next ";
411 break;
413 out << "has_previous ";
414 break;
416 out << "has_both ";
417 break;
419 out << "has_wrap_around ";
420 break;
421 }
422 out << std::endl;
423}

◆ wrap_around()

bool IdentifierField::wrap_around ( ) const
inline

Definition at line 118 of file IdentifierField.h.

Member Data Documentation

◆ invalidValues

auto IdentifierField::invalidValues = element_vector{}
staticconstexpr

Definition at line 94 of file IdentifierField.h.

94{};

◆ m_continuation_mode

continuation_mode IdentifierField::m_continuation_mode {none}
private

Definition at line 208 of file IdentifierField.h.

208{none};

◆ m_data

std::variant<element_vector, BoundedRange> IdentifierField::m_data {}
private

Definition at line 202 of file IdentifierField.h.

202{};

◆ m_empty

bool IdentifierField::m_empty {true}
private

Definition at line 207 of file IdentifierField.h.

207{true};

◆ m_indexes

index_vector IdentifierField::m_indexes {}
private

Definition at line 203 of file IdentifierField.h.

203{};

◆ m_maximum

element_type IdentifierField::m_maximum {}
private

Definition at line 201 of file IdentifierField.h.

201{};

◆ m_maxNumberOfIndices

int IdentifierField::m_maxNumberOfIndices = 100
staticconstexprprivate

Definition at line 191 of file IdentifierField.h.

◆ m_minimum

element_type IdentifierField::m_minimum {}
private

Definition at line 200 of file IdentifierField.h.

200{};

◆ m_next

element_type IdentifierField::m_next {}
private

Definition at line 206 of file IdentifierField.h.

206{};

◆ m_previous

element_type IdentifierField::m_previous {}
private

Definition at line 205 of file IdentifierField.h.

205{};

◆ m_size

size_type IdentifierField::m_size {}
private

Definition at line 204 of file IdentifierField.h.

204{};

◆ maximum_possible

auto IdentifierField::maximum_possible = std::numeric_limits<element_type>::max()
staticconstexpr

Definition at line 93 of file IdentifierField.h.

◆ minimum_possible

auto IdentifierField::minimum_possible = std::numeric_limits<element_type>::min()
staticconstexpr

Definition at line 92 of file IdentifierField.h.


The documentation for this class was generated from the following files: