@@ -11,114 +11,101 @@ namespace nanotime {
11
11
12
12
struct interval {
13
13
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 ) { }
19
15
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
+
28
27
// if any of the constructor parameters is NA, we construct an NA interval:
29
28
if (s_p.time_since_epoch () == duration::min () || e_p.time_since_epoch () == duration::min () ||
30
29
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;
33
32
} else {
34
33
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;
37
36
Rf_warning (" NAs produced by time overflow (remember that interval times are coded with 63 bits)" );
38
37
}
39
38
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;
42
41
Rf_warning (" NAs produced by time overflow (remember that interval times are coded with 63 bits)" );
43
42
}
44
- if (s > e ) {
43
+ if (e () < s () ) {
45
44
std::stringstream ss;
46
- ss << " interval end (" << e << " ) smaller than interval start (" << s << " )" ;
45
+ ss << " interval end (" << e () << " ) smaller than interval start (" << s () << " )" ;
47
46
throw std::range_error (ss.str ());
48
47
}
49
48
}
50
49
}
51
50
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
+
77
60
static const std::int64_t IVAL_MAX = 4611686018427387903LL ;
78
61
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)
80
67
};
81
68
82
69
// operators:
83
70
84
71
inline duration operator -(const interval& i1, const interval& i2) {
85
- return duration (i1.s - i2.s );
72
+ return duration (i1.s () - i2.s () );
86
73
}
87
74
88
75
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 () ;
91
78
}
92
79
93
80
inline bool operator !=(const interval& i1, const interval& i2) {
94
81
return !(i1 == i2);
95
82
}
96
83
97
84
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 ;
107
94
}
108
95
}
109
96
return false ;
110
97
}
111
98
112
99
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 ;
122
109
}
123
110
}
124
111
return false ;
@@ -133,30 +120,30 @@ namespace nanotime {
133
120
}
134
121
135
122
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 () ;
138
125
return false ;
139
126
}
140
127
141
128
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 () ;
144
131
return false ;
145
132
}
146
133
147
134
inline interval operator +(const interval& i, const duration d) {
148
135
// 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 () );
150
137
}
151
138
152
139
inline interval operator -(const interval& i, const duration d) {
153
140
// 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 () );
155
142
}
156
143
157
144
inline interval operator +(const duration d, const interval& i) {
158
145
// 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 () );
160
147
}
161
148
162
149
// interval components comparators:
@@ -195,10 +182,10 @@ namespace nanotime {
195
182
196
183
// interval comparators:
197
184
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 () );
199
186
}
200
187
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 () );
202
189
}
203
190
inline bool start_le (const interval& i1, const interval& i2) {
204
191
return !start_gt (i1,i2);
@@ -207,10 +194,10 @@ namespace nanotime {
207
194
return !start_lt (i1,i2);
208
195
}
209
196
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 () );
211
198
}
212
199
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 () );
214
201
}
215
202
inline bool end_le (const interval& i1, const interval& i2) {
216
203
return !end_gt (i1,i2);
@@ -222,10 +209,10 @@ namespace nanotime {
222
209
// / True if the end of 'i1' is smaller than the start of 'i2'. This
223
210
// / tests that 'i1' and 'i2' are disjoint and 'i2' is after 'i1'.
224
211
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 () );
226
213
}
227
214
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 () );
229
216
}
230
217
// / True if the end of 'i1' is greater or equal than the start of
231
218
// / 'i2'. This tests that 'i1' and 'i2' "touch" and that 'i2' is
@@ -277,10 +264,10 @@ namespace nanotime {
277
264
278
265
// interval comparators:
279
266
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 () );
281
268
}
282
269
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 () );
284
271
}
285
272
inline bool union_start_le (const interval& i1, const interval& i2) {
286
273
return !union_start_gt (i1,i2);
@@ -289,10 +276,10 @@ namespace nanotime {
289
276
return !union_start_lt (i1,i2);
290
277
}
291
278
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 () );
293
280
}
294
281
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 () );
296
283
}
297
284
inline bool union_end_le (const interval& i1, const interval& i2) {
298
285
return !union_end_gt (i1,i2);
@@ -304,10 +291,10 @@ namespace nanotime {
304
291
// / True if the end of 'i1' is smaller than the start of 'i2'. This
305
292
// / tests that 'i1' and 'i2' are disjoint and 'i2' is after 'i1'.
306
293
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 () );
308
295
}
309
296
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 () );
311
298
}
312
299
// / True if the end of 'i1' is greater or equal than the start of
313
300
// / 'i2'. This tests that 'i1' and 'i2' "touch" and that 'i2' is
0 commit comments