forked from kvtsang/Supera
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Range.h
145 lines (130 loc) · 3.98 KB
/
Range.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/**
* \file Range.h
*
* \ingroup Utils
*
* \brief Class def header for a class Range
*
* @author kazuhiro
*/
/** \addtogroup Utils
@{*/
#ifndef __LARCVUTIL_RANGE_H__
#define __LARCVUTIL_RANGE_H__
#include <vector>
#include <iostream>
#include <stdexcept>
namespace larcv {
template <class T>
class UniqueRangeSet;
/**
\class Range
@brief represents a "Range" w/ notion of ordering.
A range is defined by a pair of "start" and "end" values. This is stored in std::pair \n
attribute larcv::Range::_window. This attribute is protected so that the start/end cannot \n
be changed w/o a check that start is always less than end. Note the specialization \n
requires a template class T to have less operator implemented. \n
*/
template <class T>
class Range {
// Make it a friend so UniqueRangeSet can access protected guys
friend class UniqueRangeSet<T>;
public:
/// Default ctor
Range() : _valid(false)
{}
/// Enforced ctor. start must be less than end.
Range(const T& start,
const T& end)
: _window(start, end)
, _valid(true)
{ if (start > end) throw std::runtime_error("Inserted invalid range: end before start."); }
/// Default dtor
~Range() {}
/// validity
bool valid() const { return _valid; }
/// "start" accessor
const T& Start() const { return _window.first; }
/// "end" accessor
const T& End() const { return _window.second; }
/// Setter
void Set(const T& s, const T& e)
{
if (s > e) throw std::runtime_error("Inserted invalid range: end before start.");
_window.first = s;
_window.second = e;
_valid = true;
}
/// Checker (if value is inside range or not)
inline bool Inside(const T& v) const
{ return _window.first <= v && v <= _window.second; }
/// Checker (if value is outside range or not)
inline bool Outside(const T& v) const
{ return !(this->Inside(v)); }
//
// Ordering w/ another Range
//
inline bool operator< (const Range& rhs) const
{return ( _window.second < rhs.Start() ); }
inline bool operator> (const Range& rhs) const
{return ( _window.first > rhs.End() ); }
inline bool operator==(const Range& rhs) const
{return ( _window.first == rhs.Start() && _window.second == rhs.End() ); }
inline bool operator!=(const Range& rhs) const
{return !( (*this) == rhs ); }
//
// Ordering w/ T
//
inline bool operator< (const T& rhs) const
{return (_window.second < rhs); }
inline bool operator> (const T& rhs) const
{return (_window.first > rhs); }
/// Merge two larcv::Range into 1
inline Range<T> operator+ (const Range<T>& rhs) const
{
Range<T> res(*this);
res.Set(std::min( _window.first, rhs.Start() ),
std::max( _window.second, rhs.End() ) );
return res;
}
inline Range<T>& operator+= (const Range<T>& rhs)
{
_window.first = std::min( _window.first, rhs.Start() );
_window.second = std::max( _window.second, rhs.End() );
return (*this);
}
inline Range<T>& operator+= (const T& rhs)
{
_window.first = std::min( _window.first, rhs );
_window.second = std::max( _window.second, rhs );
return (*this);
}
/*
void Merge(const Range& a) {
_window.first = std::min( _window.first, a.Start() );
_window.second = std::max( _window.second, a.End() );
}
*/
protected:
/// Protected to avoid user's illegal modification on first/second (sorry users!)
std::pair<T, T> _window;
/// For validity
bool _valid;
};
}
namespace std {
// Implement pointer comparison in case it's useful
template <class T>
/**
\class less
Implementation of std::less for larcv::Range pointers
*/
class less<larcv::Range<T>*>
{
public:
bool operator()( const larcv::Range<T>* lhs, const larcv::Range<T>* rhs )
{ return (*lhs) < (*rhs); }
};
}
#endif
/** @} */ // end of doxygen group