Skip to content

Commit f2760e2

Browse files
committed
Made interval types meaningful.
1 parent a661ab1 commit f2760e2

File tree

4 files changed

+1224
-148
lines changed

4 files changed

+1224
-148
lines changed
+21-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,25 @@
11
#pragma once
22

3-
#if defined(__cpp_concepts) && __cpp_concepts >= 202002L
4-
# define LIB_INTERVAL_TREE_CONCEPTS
3+
// define LIB_INTERVAL_TREE_CONCEPTS to override the concepts feature test
4+
#ifndef LIB_INTERVAL_TREE_CONCEPTS
5+
# if defined(__cpp_concepts) && __cpp_concepts >= 202002L
6+
# define LIB_INTERVAL_TREE_CONCEPTS
7+
# endif
58
#endif
69

7-
namespace lib_interval_tree
8-
{
9-
}
10+
// define LIB_INTERVAL_TREE_DEPRECATED if __attribute__((deprecated)) is not supported
11+
#ifndef LIB_INTERVAL_TREE_DEPRECATED
12+
# if __has_cpp_attribute(depreacted)
13+
# define LIB_INTERVAL_TREE_DEPRECATED [[deprecated]]
14+
# else
15+
# define LIB_INTERVAL_TREE_DEPRECATED __attribute__((deprecated))
16+
# endif
17+
#endif
18+
19+
#ifndef LIB_INTERVAL_TREE_FALLTHROUGH
20+
# if __has_cpp_attribute(fallthrough)
21+
# define LIB_INTERVAL_TREE_FALLTHROUGH [[fallthrough]]
22+
# else
23+
# define LIB_INTERVAL_TREE_FALLTHROUGH __attribute__((fallthrough))
24+
# endif
25+
#endif

include/interval-tree/interval_tree.hpp

+183-26
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "interval_tree_fwd.hpp"
44
#include "interval_types.hpp"
55
#include "tree_hooks.hpp"
6+
#include "feature_test.hpp"
67

78
#include <string>
89
#include <memory>
@@ -26,8 +27,8 @@ namespace lib_interval_tree
2627
// ############################################################################################################
2728
using default_interval_value_type = int;
2829
// ############################################################################################################
29-
template <typename numerical_type, typename interval_kind_ = closed>
30-
struct interval
30+
template <typename numerical_type, typename interval_kind_>
31+
struct interval_base
3132
{
3233
public:
3334
using value_type = numerical_type;
@@ -40,7 +41,7 @@ namespace lib_interval_tree
4041
# if __cplusplus >= 201703L
4142
constexpr
4243
# endif
43-
interval(value_type low, value_type high)
44+
interval_base(value_type low, value_type high)
4445
: low_{low}
4546
, high_{high}
4647
{
@@ -51,52 +52,86 @@ namespace lib_interval_tree
5152
# if __cplusplus >= 201703L
5253
constexpr
5354
# endif
54-
interval(value_type low, value_type high)
55+
interval_base(value_type low, value_type high)
5556
: low_{std::min(low, high)}
5657
, high_{std::max(low, high)}
5758
{}
5859
#endif
59-
virtual ~interval() = default;
60+
virtual ~interval_base() = default;
6061

6162
/**
62-
* Returns if both intervals equal.
63+
* Returns the lower bound of the interval
6364
*/
64-
friend bool operator==(interval const& lhs, interval const& other)
65+
value_type low() const
6566
{
66-
return lhs.low_ == other.low_ && lhs.high_ == other.high_;
67+
return low_;
6768
}
6869

6970
/**
70-
* Returns if both intervals are different.
71+
* Returns the upper bound of the interval
7172
*/
72-
friend bool operator!=(interval const& lhs, interval const& other)
73+
value_type high() const
7374
{
74-
return lhs.low_ != other.low_ || lhs.high_ != other.high_;
75+
return high_;
7576
}
7677

78+
protected:
79+
value_type low_;
80+
value_type high_;
81+
};
82+
// ############################################################################################################
83+
template <typename numerical_type, typename interval_kind_ = closed>
84+
struct interval : public interval_base<numerical_type, interval_kind_>
85+
{
86+
public:
87+
using value_type = typename interval_base<numerical_type, interval_kind_>::value_type;
88+
using interval_kind = typename interval_base<numerical_type, interval_kind_>::interval_kind;
89+
90+
using interval_base<numerical_type, interval_kind_>::low;
91+
using interval_base<numerical_type, interval_kind_>::high;
92+
93+
using interval_base<numerical_type, interval_kind_>::low_;
94+
using interval_base<numerical_type, interval_kind_>::high_;
95+
7796
/**
78-
* Returns the lower bound of the interval
97+
* Constructs an interval. low MUST be smaller than high.
7998
*/
80-
value_type low() const
99+
#if __cplusplus >= 201703L
100+
constexpr
101+
#endif
102+
interval(value_type low, value_type high)
103+
: interval_base<numerical_type, interval_kind_>{low, high}
104+
{}
105+
106+
/**
107+
* Returns true if both intervals equal.
108+
*/
109+
friend bool operator==(
110+
interval<numerical_type, interval_kind_> const& lhs,
111+
interval<numerical_type, interval_kind_> const& rhs
112+
)
81113
{
82-
return low_;
114+
return lhs.low_ == rhs.low_ && lhs.high_ == rhs.high_;
83115
}
84116

85117
/**
86-
* Returns the upper bound of the interval
118+
* Returns true if both intervals are different.
87119
*/
88-
value_type high() const
120+
friend bool operator!=(
121+
interval<numerical_type, interval_kind_> const& lhs,
122+
interval<numerical_type, interval_kind_> const& rhs
123+
)
89124
{
90-
return high_;
125+
return lhs.low_ != rhs.low_ || lhs.high_ != rhs.high_;
91126
}
92127

93128
/**
94129
* Returns whether the intervals overlap.
95130
* For when both intervals are closed.
96131
*/
97-
bool overlaps(value_type l, value_type h) const
132+
LIB_INTERVAL_TREE_DEPRECATED bool overlaps(value_type l, value_type h) const
98133
{
99-
return low_ <= h && l <= high_;
134+
return interval_kind::overlaps(low_, high_, l, h);
100135
}
101136

102137
/**
@@ -113,7 +148,7 @@ namespace lib_interval_tree
113148
*/
114149
bool overlaps(interval const& other) const
115150
{
116-
return overlaps(other.low_, other.high_);
151+
return interval_kind::overlaps(low_, high_, other.low_, other.high_);
117152
}
118153

119154
/**
@@ -137,7 +172,7 @@ namespace lib_interval_tree
137172
*/
138173
bool within(interval const& other) const
139174
{
140-
return low_ <= other.low_ && high_ >= other.high_;
175+
return within(other.low_) && within(other.high_);
141176
}
142177

143178
/**
@@ -148,18 +183,113 @@ namespace lib_interval_tree
148183
{
149184
if (overlaps(other))
150185
return 0;
151-
if (high_ < other.low_)
186+
if (high_ <= other.low_)
152187
return other.low_ - high_;
153188
else
154189
return low_ - other.high_;
155190
}
156191

192+
/**
193+
* Creates a new interval from this and other, that contains both intervals and whatever
194+
* is between.
195+
*/
196+
interval join(interval const& other) const
197+
{
198+
return {std::min(low_, other.low_), std::max(high_, other.high_)};
199+
}
200+
157201
/**
158202
* Returns the size of the interval.
159203
*/
160204
value_type size() const
161205
{
162-
return high_ - low_;
206+
return interval_kind::size(low_, high_);
207+
}
208+
};
209+
210+
template <typename numerical_type>
211+
struct interval<numerical_type, dynamic> : public interval_base<numerical_type, dynamic>
212+
{
213+
public:
214+
using value_type = typename interval_base<numerical_type, dynamic>::value_type;
215+
using interval_kind = dynamic;
216+
217+
/**
218+
* Constructs an interval. low MUST be smaller than high.
219+
*/
220+
#if __cplusplus >= 201703L
221+
constexpr
222+
#endif
223+
interval(value_type low, value_type high, interval_border leftBorder, interval_border rightBorder)
224+
: interval_base<numerical_type, interval_kind>{low, high}
225+
, left_border_{leftBorder}
226+
, right_border_{rightBorder}
227+
{}
228+
229+
/**
230+
* Returns true if both intervals equal.
231+
*/
232+
friend bool
233+
operator==(interval<numerical_type, dynamic> const& lhs, interval<numerical_type, dynamic> const& other)
234+
{
235+
return lhs.low_ == other.low_ && lhs.high_ == other.high_ && lhs.left_border_ == other.left_border_ &&
236+
lhs.right_border_ == other.right_border_;
237+
}
238+
239+
/**
240+
* Returns true if both intervals are different.
241+
*/
242+
friend bool
243+
operator!=(interval<numerical_type, dynamic> const& lhs, interval<numerical_type, dynamic> const& other)
244+
{
245+
return lhs.low_ != other.low_ || lhs.high_ != other.high_ || lhs.left_border_ != other.left_border_ ||
246+
lhs.right_border_ != other.right_border_;
247+
}
248+
249+
using interval_base<numerical_type, interval_kind>::low;
250+
using interval_base<numerical_type, interval_kind>::high;
251+
using interval_base<numerical_type, interval_kind>::low_;
252+
using interval_base<numerical_type, interval_kind>::high_;
253+
254+
/**
255+
* Returns whether the intervals overlap
256+
*/
257+
bool overlaps(interval const& other) const
258+
{
259+
return interval_kind::overlaps(*this, other);
260+
}
261+
262+
/**
263+
* Returns whether the intervals overlap exclusively, independent of border.
264+
*/
265+
bool overlaps_exclusive(interval const& other) const
266+
{
267+
return low_ < other.high_ && other.low_ < high_;
268+
}
269+
270+
/**
271+
* Returns whether the given value is in this.
272+
*/
273+
bool within(value_type value) const
274+
{
275+
return interval_kind::within(*this, value);
276+
}
277+
278+
/**
279+
* Returns whether the given interval is in this.
280+
*/
281+
bool within(interval const& other) const
282+
{
283+
return within(other.low_) && within(other.high_);
284+
}
285+
286+
/**
287+
* Calculates the distance between the two intervals.
288+
* Overlapping intervals have 0 distance.
289+
*/
290+
value_type operator-(interval const& other) const
291+
{
292+
interval_kind::distance(*this, other);
163293
}
164294

165295
/**
@@ -168,13 +298,40 @@ namespace lib_interval_tree
168298
*/
169299
interval join(interval const& other) const
170300
{
171-
return {std::min(low_, other.low_), std::max(high_, other.high_)};
301+
return interval_kind::join(*this, other);
302+
}
303+
304+
/**
305+
* Returns the size of the interval.
306+
*/
307+
value_type size() const
308+
{
309+
return interval_kind::size(*this);
310+
}
311+
312+
/**
313+
* @brief Returns the left border type of the interval.
314+
*
315+
*/
316+
interval_border left_border() const
317+
{
318+
return left_border_;
319+
}
320+
321+
/**
322+
* @brief Returns the right border type of the interval.
323+
*
324+
*/
325+
interval_border right_border() const
326+
{
327+
return right_border_;
172328
}
173329

174330
protected:
175-
value_type low_;
176-
value_type high_;
331+
interval_border left_border_;
332+
interval_border right_border_;
177333
};
334+
178335
// ############################################################################################################
179336
/**
180337
* Creates a safe interval that puts the lower bound left automatically.

0 commit comments

Comments
 (0)