@@ -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
0 commit comments