Skip to content

Commit 36354a2

Browse files
committed
incomplete solution for bitfield removal - NA is not yet handled correctly
1 parent a7b9be7 commit 36354a2

File tree

3 files changed

+109
-122
lines changed

3 files changed

+109
-122
lines changed

inst/include/nanotime/interval.hpp

Lines changed: 74 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -11,114 +11,101 @@ namespace nanotime {
1111

1212
struct interval {
1313

14-
#ifdef WORDS_BIGENDIAN
15-
constexpr interval() : s(0), sopen(0), e(0), eopen(0) { }
16-
#else
17-
constexpr interval() : sopen(0), s(0), eopen(0), e(0) { }
18-
#endif
14+
constexpr interval() : s_impl(0), e_impl(0) { }
1915

20-
interval(dtime s_p, dtime e_p, int sopen_p, int eopen_p)
21-
#ifdef WORDS_BIGENDIAN
22-
: s(s_p.time_since_epoch().count()), sopen(sopen_p),
23-
e(e_p.time_since_epoch().count()), eopen(eopen_p) {
24-
#else
25-
: sopen(sopen_p), s(s_p.time_since_epoch().count()),
26-
eopen(eopen_p), e(e_p.time_since_epoch().count()) {
27-
#endif
16+
interval(dtime s_p, dtime e_p, int sopen_p, int eopen_p) :
17+
s_impl(s_p.time_since_epoch().count()),
18+
e_impl(e_p.time_since_epoch().count())
19+
{
20+
if (sopen_p) {
21+
s_impl |= std::int64_t{1} << 63;
22+
}
23+
if (eopen_p) {
24+
e_impl |= std::int64_t{1} << 63;
25+
}
26+
2827
// if any of the constructor parameters is NA, we construct an NA interval:
2928
if (s_p.time_since_epoch() == duration::min() || e_p.time_since_epoch() == duration::min() ||
3029
sopen_p == NA_INTEGER || eopen_p == NA_INTEGER) {
31-
s = IVAL_NA;
32-
e = IVAL_NA;
30+
s_impl = IVAL_NA;
31+
e_impl = IVAL_NA;
3332
} else {
3433
if (s_p.time_since_epoch().count() < IVAL_MIN || e_p.time_since_epoch().count() < IVAL_MIN) {
35-
s = IVAL_NA;
36-
e = IVAL_NA;
34+
s_impl= IVAL_NA;
35+
e_impl = IVAL_NA;
3736
Rf_warning("NAs produced by time overflow (remember that interval times are coded with 63 bits)");
3837
}
3938
if (s_p.time_since_epoch().count() > IVAL_MAX || e_p.time_since_epoch().count() > IVAL_MAX) {
40-
s = IVAL_NA;
41-
e = IVAL_NA;
39+
s_impl = IVAL_NA;
40+
e_impl = IVAL_NA;
4241
Rf_warning("NAs produced by time overflow (remember that interval times are coded with 63 bits)");
4342
}
44-
if (s > e) {
43+
if (e() < s()) {
4544
std::stringstream ss;
46-
ss << "interval end (" << e << ") smaller than interval start (" << s << ")";
45+
ss << "interval end (" << e() << ") smaller than interval start (" << s() << ")";
4746
throw std::range_error(ss.str());
4847
}
4948
}
5049
}
5150

52-
// interval(std::int64_t s_p, std::int64_t e_p, bool sopen_p, bool eopen_p)
53-
// : sopen(sopen_p), s(s_p), eopen(eopen_p), e(e_p) {
54-
// if (s > e) {
55-
// std::stringstream ss;
56-
// ss << "interval end (" << e << ") smaller than interval start (" << s << ")";
57-
// throw std::range_error(ss.str());
58-
// }
59-
// }
60-
61-
dtime getStart() const { return dtime(duration(s)); }
62-
dtime getEnd() const { return dtime(duration(e)); }
63-
bool isNA() const { return s == IVAL_NA; }
64-
65-
#ifdef WORDS_BIGENDIAN
66-
std::int64_t s : 63;
67-
bool sopen : 1; // encode if the interval's start boundary is open (true) or closed (false)
68-
std::int64_t e : 63;
69-
bool eopen : 1; // encode if the interval's end boundary is open (true) or closed (false)
70-
#else
71-
bool sopen : 1; // encode if the interval's start boundary is open (true) or closed (false)
72-
std::int64_t s : 63;
73-
bool eopen : 1; // encode if the interval's end boundary is open (true) or closed (false)
74-
std::int64_t e : 63;
75-
#endif
76-
51+
dtime getStart() const { return dtime(duration(s_impl)); }
52+
dtime getEnd() const { return dtime(duration(e_impl)); }
53+
bool sopen() const { return (s_impl & (std::int64_t{1} << 63)) != 0; }
54+
bool eopen() const { return (e_impl & (std::int64_t{1} << 63)) != 0; }
55+
std::int64_t s() const { return s_impl & ~(std::int64_t{1} << 63); }
56+
std::int64_t e() const { return e_impl & ~(std::int64_t{1} << 63); }
57+
58+
bool isNA() const { return s_impl == IVAL_NA; }
59+
7760
static const std::int64_t IVAL_MAX = 4611686018427387903LL;
7861
static const std::int64_t IVAL_MIN = -4611686018427387903LL;
79-
static const std::int64_t IVAL_NA = -4611686018427387904LL;
62+
static const std::int64_t IVAL_NA = -9223372036854775807LL - 1;
63+
64+
private:
65+
std::int64_t s_impl; // start of ival; last bit encodes if boundary is open (1) or closed (0)
66+
std::int64_t e_impl; // end of ival; last bit encodes if boundary is open (1) or closed (0)
8067
};
8168

8269
// operators:
8370

8471
inline duration operator-(const interval& i1, const interval& i2) {
85-
return duration(i1.s - i2.s);
72+
return duration(i1.s() - i2.s());
8673
}
8774

8875
inline bool operator==(const interval& i1, const interval& i2) {
89-
return i1.s == i2.s && i1.e == i2.e && i1.sopen == i2.sopen &&
90-
i1.eopen == i2.eopen;
76+
return i1.s() == i2.s() && i1.e() == i2.e() && i1.sopen() == i2.sopen() &&
77+
i1.eopen() == i2.eopen();
9178
}
9279

9380
inline bool operator!=(const interval& i1, const interval& i2) {
9481
return !(i1 == i2);
9582
}
9683

9784
inline bool operator<=(const interval& i1, const interval& i2) {
98-
if (i1.s < i2.s) return true;
99-
if (i1.s == i2.s) {
100-
if (!i1.sopen && i2.sopen) return true;
101-
if (i1.sopen && !i2.sopen) return false;
102-
// here we know that s1.sopen == s2.sopen
103-
if (i1.e < i2.e) return true;
104-
if (i1.e == i2.e) {
105-
if (i1.eopen == i2.eopen) return true;
106-
if (i1.eopen && !i2.eopen) return true;
85+
if (i1.s() < i2.s()) return true;
86+
if (i1.s() == i2.s()) {
87+
if (!i1.sopen() && i2.sopen()) return true;
88+
if (i1.sopen() && !i2.sopen()) return false;
89+
// here we know that s1.sopen() == s2.sopen()
90+
if (i1.e() < i2.e()) return true;
91+
if (i1.e() == i2.e()) {
92+
if (i1.eopen() == i2.eopen()) return true;
93+
if (i1.eopen() && !i2.eopen()) return true;
10794
}
10895
}
10996
return false;
11097
}
11198

11299
inline bool operator<(const interval& i1, const interval& i2) {
113-
if (i1.s < i2.s) return true;
114-
if (i1.s == i2.s) {
115-
if (!i1.sopen && i2.sopen) return true;
116-
if (i1.sopen && !i2.sopen) return false;
117-
// here we know that s1.sopen == s2.sopen
118-
if (i1.e < i2.e) return true;
119-
if (i1.e == i2.e) {
120-
if (i1.eopen == i2.eopen) return false;
121-
if (i1.eopen && !i2.eopen) return true;
100+
if (i1.s() < i2.s()) return true;
101+
if (i1.s() == i2.s()) {
102+
if (!i1.sopen() && i2.sopen()) return true;
103+
if (i1.sopen() && !i2.sopen()) return false;
104+
// here we know that s1.sopen() == s2.sopen()
105+
if (i1.e() < i2.e()) return true;
106+
if (i1.e() == i2.e()) {
107+
if (i1.eopen() == i2.eopen()) return false;
108+
if (i1.eopen() && !i2.eopen()) return true;
122109
}
123110
}
124111
return false;
@@ -133,30 +120,30 @@ namespace nanotime {
133120
}
134121

135122
inline bool operator<(const dtime& i1, const interval& i2) {
136-
if (i1.time_since_epoch().count() < i2.s) return true;
137-
if (i1.time_since_epoch().count() == i2.s) return i2.sopen;
123+
if (i1.time_since_epoch().count() < i2.s()) return true;
124+
if (i1.time_since_epoch().count() == i2.s()) return i2.sopen();
138125
return false;
139126
}
140127

141128
inline bool operator>(const dtime& i1, const interval& i2) {
142-
if (i1.time_since_epoch().count() > i2.e) return true;
143-
if (i1.time_since_epoch().count() == i2.e) return i2.eopen;
129+
if (i1.time_since_epoch().count() > i2.e()) return true;
130+
if (i1.time_since_epoch().count() == i2.e()) return i2.eopen();
144131
return false;
145132
}
146133

147134
inline interval operator+(const interval& i, const duration d) {
148135
// test duration is not > 63-bits, and after that the constructor can test for overflow:
149-
return interval(i.getStart() + d, i.getEnd() + d, i.sopen, i.eopen);
136+
return interval(i.getStart() + d, i.getEnd() + d, i.sopen(), i.eopen());
150137
}
151138

152139
inline interval operator-(const interval& i, const duration d) {
153140
// test duration is not > 63-bits, and after that the constructor can test for underflow:
154-
return interval(i.getStart() - d, i.getEnd() - d, i.sopen, i.eopen);
141+
return interval(i.getStart() - d, i.getEnd() - d, i.sopen(), i.eopen());
155142
}
156143

157144
inline interval operator+(const duration d, const interval& i) {
158145
// test duration is not > 63-bits, and after that the constructor can test for overflow:
159-
return interval(i.getStart() + d, i.getEnd() + d, i.sopen, i.eopen);
146+
return interval(i.getStart() + d, i.getEnd() + d, i.sopen(), i.eopen());
160147
}
161148

162149
// interval components comparators:
@@ -195,10 +182,10 @@ namespace nanotime {
195182

196183
// interval comparators:
197184
inline bool start_lt(const interval& i1, const interval& i2) {
198-
return start_lt(i1.getStart(), i1.sopen, i2.getStart(), i2.sopen);
185+
return start_lt(i1.getStart(), i1.sopen(), i2.getStart(), i2.sopen());
199186
}
200187
inline bool start_gt(const interval& i1, const interval& i2) {
201-
return start_gt(i1.getStart(), i1.sopen, i2.getStart(), i2.sopen);
188+
return start_gt(i1.getStart(), i1.sopen(), i2.getStart(), i2.sopen());
202189
}
203190
inline bool start_le(const interval& i1, const interval& i2) {
204191
return !start_gt(i1,i2);
@@ -207,10 +194,10 @@ namespace nanotime {
207194
return !start_lt(i1,i2);
208195
}
209196
inline bool end_lt(const interval& i1, const interval& i2) {
210-
return end_lt(i1.getEnd(), i1.eopen, i2.getEnd(), i2.eopen);
197+
return end_lt(i1.getEnd(), i1.eopen(), i2.getEnd(), i2.eopen());
211198
}
212199
inline bool end_gt(const interval& i1, const interval& i2) {
213-
return end_gt(i1.getEnd(), i1.eopen, i2.getEnd(), i2.eopen);
200+
return end_gt(i1.getEnd(), i1.eopen(), i2.getEnd(), i2.eopen());
214201
}
215202
inline bool end_le(const interval& i1, const interval& i2) {
216203
return !end_gt(i1,i2);
@@ -222,10 +209,10 @@ namespace nanotime {
222209
/// True if the end of 'i1' is smaller than the start of 'i2'. This
223210
/// tests that 'i1' and 'i2' are disjoint and 'i2' is after 'i1'.
224211
inline bool end_lt_start(const interval& i1, const interval& i2) {
225-
return end_lt(i1.getEnd(), i1.eopen, i2.getStart(), i2.sopen);
212+
return end_lt(i1.getEnd(), i1.eopen(), i2.getStart(), i2.sopen());
226213
}
227214
inline bool end_gt_start(const interval& i1, const interval& i2) {
228-
return end_gt(i1.getEnd(), i1.eopen, i2.getStart(), i2.sopen);
215+
return end_gt(i1.getEnd(), i1.eopen(), i2.getStart(), i2.sopen());
229216
}
230217
/// True if the end of 'i1' is greater or equal than the start of
231218
/// 'i2'. This tests that 'i1' and 'i2' "touch" and that 'i2' is
@@ -277,10 +264,10 @@ namespace nanotime {
277264

278265
// interval comparators:
279266
inline bool union_start_lt(const interval& i1, const interval& i2) {
280-
return union_start_lt(i1.getStart(), i1.sopen, i2.getStart(), i2.sopen);
267+
return union_start_lt(i1.getStart(), i1.sopen(), i2.getStart(), i2.sopen());
281268
}
282269
inline bool union_start_gt(const interval& i1, const interval& i2) {
283-
return union_start_gt(i1.getStart(), i1.sopen, i2.getStart(), i2.sopen);
270+
return union_start_gt(i1.getStart(), i1.sopen(), i2.getStart(), i2.sopen());
284271
}
285272
inline bool union_start_le(const interval& i1, const interval& i2) {
286273
return !union_start_gt(i1,i2);
@@ -289,10 +276,10 @@ namespace nanotime {
289276
return !union_start_lt(i1,i2);
290277
}
291278
inline bool union_end_lt(const interval& i1, const interval& i2) {
292-
return union_end_lt(i1.getEnd(), i1.eopen, i2.getEnd(), i2.eopen);
279+
return union_end_lt(i1.getEnd(), i1.eopen(), i2.getEnd(), i2.eopen());
293280
}
294281
inline bool union_end_gt(const interval& i1, const interval& i2) {
295-
return union_end_gt(i1.getEnd(), i1.eopen, i2.getEnd(), i2.eopen);
282+
return union_end_gt(i1.getEnd(), i1.eopen(), i2.getEnd(), i2.eopen());
296283
}
297284
inline bool union_end_le(const interval& i1, const interval& i2) {
298285
return !union_end_gt(i1,i2);
@@ -304,10 +291,10 @@ namespace nanotime {
304291
/// True if the end of 'i1' is smaller than the start of 'i2'. This
305292
/// tests that 'i1' and 'i2' are disjoint and 'i2' is after 'i1'.
306293
inline bool union_end_lt_start(const interval& i1, const interval& i2) {
307-
return union_end_lt(i1.getEnd(), i1.eopen, i2.getStart(), i2.sopen);
294+
return union_end_lt(i1.getEnd(), i1.eopen(), i2.getStart(), i2.sopen());
308295
}
309296
inline bool union_end_gt_start(const interval& i1, const interval& i2) {
310-
return union_end_gt(i1.getEnd(), i1.eopen, i2.getStart(), i2.sopen);
297+
return union_end_gt(i1.getEnd(), i1.eopen(), i2.getStart(), i2.sopen());
311298
}
312299
/// True if the end of 'i1' is greater or equal than the start of
313300
/// 'i2'. This tests that 'i1' and 'i2' "touch" and that 'i2' is

inst/include/nanotime/period.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ namespace nanotime {
125125

126126

127127
inline interval plus (const interval& i, const period& p, const std::string& z) {
128-
return interval(plus(dtime{duration{i.s}}, p, z),
129-
plus(dtime{duration{i.e}}, p, z), i.sopen, i.eopen);
128+
return interval(plus(dtime{duration{i.s()}}, p, z),
129+
plus(dtime{duration{i.e()}}, p, z), i.sopen(), i.eopen());
130130
}
131131
inline interval plus (const period& p, const interval& i, const std::string& z) {
132132
return plus(i, p, z);

0 commit comments

Comments
 (0)