McStas Readout Master 0.3.3
Loading...
Searching...
No Matches
efu_time.h
1//
2// Created by g on 26/10/22.
3//
4
5#ifndef MCSTAS_UDP_TRANSMIT_EFU_TIME_H
6#define MCSTAS_UDP_TRANSMIT_EFU_TIME_H
7#include <chrono>
8#include <cmath>
9#include <iostream>
10#include <stdexcept>
11#include <utility>
12
19class efu_time {
20protected:
21 uint32_t _h;
22 uint32_t _l;
23public:
24 static constexpr uint64_t ticks = 88052499;
25
31 efu_time(const uint32_t high, const uint32_t low): _h(high), _l(low) {
32 if (_l > ticks) {
33 _h += _l / ticks;
34 _l %= ticks;
35 }
36 };
37
38 explicit efu_time(const std::pair<uint32_t, uint32_t> & p): _h(p.first), _l(p.second) {}
39
44 explicit efu_time(const double time)
45 : _h(static_cast<uint32_t>(time)), _l(static_cast<uint32_t>(std::fmod(time, 1.0) * ticks)) {}
46
50 efu_time(): _h(0), _l(0) {
51 using std::chrono::duration_cast, std::chrono::nanoseconds, std::chrono::system_clock;
52 constexpr uint64_t nps = 1000000000u; // nanoseconds per second
53 const auto ns = duration_cast<nanoseconds>(system_clock::now().time_since_epoch()).count();
54 const auto seconds = ns / nps;
55 const auto tick_count = ((ns % nps) * ticks) / nps;
56 _h = static_cast<uint32_t>(seconds);
57 _l = static_cast<uint32_t>(tick_count);
58 }
59
60 uint32_t high() const {return _h;}
61 uint32_t low() const {return _l;}
62
63 bool operator==(const efu_time& other) const {
64 return (_h == other._h) && (_l == other._l);
65 }
66 bool operator<(const efu_time& other) const {
67 if (_h < other._h) return true;
68 if (_h > other._h) return false;
69 return _l < other._l;
70 }
71 bool operator>(const efu_time& other) const {
72 if (_h > other._h) return true;
73 if (_h < other._h) return false;
74 return _l > other._l;
75 }
76
77 bool operator>=(const efu_time & other) const {
78 return !(*this < other);
79 }
80
81 bool operator>=(const efu_time * other) const {
82 return *this >= *other;
83 }
84
85 efu_time operator+(const efu_time & other) const {
86 // the constructor ensures l is always less than ticks
87 // and 2*ticks is _well_ within the dynamic range of uint32_t
88 return {_h + other._h, _l + other._l};
89 }
90
91 efu_time operator+(const efu_time * other) const {
92 return *this + *other;
93 }
94
95 efu_time operator-(const efu_time & other) const {
96 if (*this < other) {
97 std::cout << *this << " - " << other << std::endl;
98 throw std::runtime_error("Subtracting a larger time?");
99 }
100 uint32_t h = _h - other._h;
101 if (_l >= other._l) return {h, _l - other._l};
102 auto r = ticks + static_cast<uint64_t>(_l) - static_cast<uint64_t>(other._l);
103 return {h - 1u, static_cast<uint32_t>(r)};
104 }
105
106 efu_time operator-(const efu_time * other) const {
107 return *this - *other;
108 }
109
110 uint64_t total_ticks() const {
111 return static_cast<uint64_t>(_h) * ticks + static_cast<uint64_t>(_l);
112 }
113
114 uint64_t total_nanoseconds() const {
115 constexpr uint64_t nps = 1000000000u;
116 return static_cast<uint64_t>(_h) * nps + (static_cast<uint64_t>(_l) * nps) / ticks;
117 }
118
119 uint32_t operator/(const efu_time & other) const {
120 return static_cast<uint32_t>(total_ticks() / other.total_ticks());
121 }
122
123 efu_time operator*(const uint32_t m) const {
124 auto h = _h * m;
125 auto r = static_cast<uint64_t>(_l) * static_cast<uint64_t>(m);
126 if (r > ticks){
127 h += static_cast<uint32_t>(r / ticks);
128 r = r % ticks;
129 }
130 return {h, static_cast<uint32_t>(r)};
131 }
132
133 efu_time operator%(const efu_time& m) const {
134 return *this - m * (*this / m);
135 }
136
137 efu_time operator%(const efu_time * m) const {
138 return *this % *m;
139 }
140
141 friend std::ostream& operator<<(std::ostream& os, const efu_time& dt) {
142 os << "(" << dt.high() << "," << dt.low() << ")";
143 return os;
144 }
145 friend std::ostream & operator<<(std::ostream& os, const efu_time* dt) {
146 os << "(" << dt->high() << "," << dt->low() << ")";
147 return os;
148 }
149};
150
151#endif // MCSTAS_UDP_TRANSMIT_EFU_TIME_H
ESS EFU two-integer timestamp: whole seconds since the UNIX epoch plus ticks of the 88....
Definition efu_time.h:19
efu_time(const double time)
Conversion from floating point time representation.
Definition efu_time.h:44
efu_time(const uint32_t high, const uint32_t low)
A time equivalent to that used in the ESS Event-Formation-Unit.
Definition efu_time.h:31
efu_time()
Use the system clock to construct an EFU consistent time stamp.
Definition efu_time.h:50