MotionLib  1.0.0
SamBuCa motion library
Units.hxx
1 /*
2  * Copyright (C) 2022 CERN
3  *
4  * This software is provided 'as-is', without any express or implied
5  * warranty. In no event will the authors be held liable for any damages
6  * arising from the use of this software.
7  *
8  * Permission is granted to anyone to use this software for any purpose,
9  * including commercial applications, and to alter it and redistribute it
10  * freely, subject to the following restrictions:
11  *
12  * 1. The origin of this software must not be misrepresented; you must not
13  * claim that you wrote the original software. If you use this software
14  * in a product, an acknowledgment in the product documentation would be
15  * appreciated but is not required.
16  * 2. Altered source versions must be plainly marked as such, and must not be
17  * misrepresented as being the original software.
18  * 3. This notice may not be removed or altered from any source distribution.
19  *
20  * Created on: 2022-02-09
21  * Author: Michal Mysior <mmysior> <michal.mysior@cern.ch>
22  *
23  */
24 
25 #ifndef MOTION_CONTROLLER_UNITS_HXX__
26 #define MOTION_CONTROLLER_UNITS_HXX__
27 
28 #include "Exception.hpp"
29 #include "Units.hpp"
30 #include <type_traits>
31 
32 namespace smc {
33 namespace units {
34 
40 template<class R, class P>
41 Value operator*(const Value &value, std::chrono::duration<R, P> duration)
42 {
43  switch (value.unit)
44  {
45  case Unit::MILLIMETERS_PER_MINUTE:
46  return Value{
47  Unit::MILLIMETERS,
48  (value.value *
49  std::chrono::duration_cast<std::chrono::minutes>(duration).count())};
50  case Unit::METERS_PER_SECOND:
51  return Value{
52  Unit::METERS,
53  (value.value *
54  std::chrono::duration_cast<std::chrono::seconds>(duration).count())};
55  case Unit::MILLIMETERS_PER_SECOND:
56  return Value{
57  Unit::MILLIMETERS,
58  (value.value *
59  std::chrono::duration_cast<std::chrono::seconds>(duration).count())};
60  case Unit::MILLIMETERS_PER_SECOND_SQUARED:
61  return Value{
62  Unit::MILLIMETERS_PER_SECOND,
63  (value.value *
64  std::chrono::duration_cast<std::chrono::seconds>(duration).count())};
65  default: throw Exception{ErrorCode::IncompatibleUnits};
66  }
67 }
68 
69 template<class R, class P>
70 Value operator/(const Value &value, std::chrono::duration<R, P> duration)
71 {
72  switch (value.unit)
73  {
74  case Unit::MILLIMETERS:
75  if (std::is_same<typename std::chrono::duration<R, P>::period,
76  std::chrono::minutes::period>::value)
77  {
78  return Value{
79  Unit::MILLIMETERS_PER_MINUTE,
80  (value.value / duration.count())};
81  }
82  else
83  {
84  // default to returning mm/s
85  return Value{
86  Unit::MILLIMETERS_PER_SECOND,
87  (value.value /
88  std::chrono::duration_cast<std::chrono::seconds>(duration).count())};
89  }
90  case Unit::METERS:
91  return Value{
92  Unit::METERS_PER_SECOND,
93  (value.value /
94  std::chrono::duration_cast<std::chrono::seconds>(duration).count())};
95  case Unit::MILLIMETERS_PER_SECOND:
96  return Value{
97  Unit::MILLIMETERS_PER_SECOND_SQUARED,
98  (value.value /
99  std::chrono::duration_cast<std::chrono::seconds>(duration).count())};
100  default: throw Exception{ErrorCode::IncompatibleUnits};
101  }
102 }
103 
105 {
106  reference(const reference &) = default;
107  reference &operator=(const reference &) = delete;
108  inline operator bool() const
109  {
110  return (const_cast<const IOPort &>(*m_port))[m_offset];
111  }
112  inline reference &operator=(bool value)
113  {
114  if (value)
115  m_port->value |= (value_type(1) << m_offset);
116  else
117  m_port->value &= ~(value_type(1) << m_offset);
118  return *this;
119  }
120 
121  inline size_type offset() const { return m_offset; }
122  bool operator==(const reference &ref) const
123  {
124  return m_offset == ref.m_offset && m_port == ref.m_port;
125  }
126  bool operator!=(const reference &ref) const { return !(ref == *this); }
127 
128 protected:
129  reference(size_type offset, IOPort *port) :
130  m_offset{offset}, m_port{port} {};
131 
132  friend struct IOPort;
133  friend struct const_reference;
134  size_type m_offset;
135  IOPort *m_port;
136 };
137 
138 inline IOPort::reference IOPort::operator[](size_type offset)
139 {
140  return reference{offset, this};
141 }
142 
144 {
145  const_reference(const reference &ref) :
146  m_offset{ref.m_offset}, m_port{ref.m_port} {};
147  const_reference(const const_reference &) = default;
148  const_reference &operator=(const const_reference &) = delete;
149  inline operator bool() const { return (*m_port)[m_offset]; }
150  inline size_type offset() const { return m_offset; }
151  bool operator==(const const_reference &ref) const
152  {
153  return m_offset == ref.m_offset && m_port == ref.m_port;
154  }
155  bool operator!=(const reference &ref) const { return !(ref == *this); }
156 
157 protected:
158  const_reference(size_type offset, const IOPort *port) :
159  m_offset{offset}, m_port{port} {};
160 
161  friend struct IOPort;
162  size_type m_offset;
163  const IOPort *m_port;
164 };
165 
167 {
168  iterator(reference &&ref) : _ref{ref} {}
169  iterator() : _ref{0, nullptr} {}
170 
171  reference &operator*() { return _ref; }
172  reference *operator->() { return &_ref; }
173  bool operator==(const iterator &it) const { return _ref == it._ref; }
174  bool operator!=(const iterator &it) const { return _ref != it._ref; }
175 
176  iterator &operator++()
177  {
178  ++_ref.m_offset;
179  return *this;
180  }
181  iterator operator++(int)
182  {
183  iterator tmp = *this;
184  ++_ref.m_offset;
185  return tmp;
186  }
187  iterator &operator--()
188  {
189  --_ref.m_offset;
190  return *this;
191  }
192  iterator operator--(int)
193  {
194  iterator tmp = *this;
195  --_ref.m_offset;
196  return tmp;
197  }
198 
199 protected:
200  friend struct IOPort::const_iterator;
201  reference _ref;
202 };
203 
205 {
206  const_iterator(const_reference &&ref) : _ref{ref} {}
207  const_iterator(const iterator &it) : _ref{it._ref} {}
208  const_iterator() : _ref{0, nullptr} {}
209 
210  const_reference &operator*() { return _ref; }
211  const_reference *operator->() { return &_ref; }
212  bool operator==(const const_iterator &it) const { return it._ref == _ref; }
213  bool operator!=(const const_iterator &it) const { return it._ref != _ref; }
214 
215  const_iterator &operator++()
216  {
217  ++_ref.m_offset;
218  return *this;
219  }
220  const_iterator operator++(int)
221  {
222  const_iterator tmp = *this;
223  ++_ref.m_offset;
224  return tmp;
225  }
226  const_iterator &operator--()
227  {
228  --_ref.m_offset;
229  return *this;
230  }
231  const_iterator operator--(int)
232  {
233  const_iterator tmp = *this;
234  --_ref.m_offset;
235  return tmp;
236  }
237 
238 protected:
239  const_reference _ref;
240 };
241 
242 inline IOPort::const_iterator IOPort::begin() const
243 {
244  return const_iterator{const_reference{0, this}};
245 }
246 
247 inline IOPort::const_iterator IOPort::end() const
248 {
249  return const_iterator{const_reference{size, this}};
250 }
251 
252 inline IOPort::const_iterator IOPort::const_begin() const
253 {
254  return begin();
255 }
256 
257 inline IOPort::const_iterator IOPort::const_end() const
258 {
259  return end();
260 }
261 
262 inline IOPort::iterator IOPort::begin()
263 {
264  return iterator{reference{0, this}};
265 }
266 
267 inline IOPort::iterator IOPort::end()
268 {
269  return iterator{reference{size, this}};
270 }
271 
274 } /* namespace units */
275 } /* namespace smc */
276 
277 namespace std {
278 
279 template<>
280 struct hash<smc::units::Unit>
281 {
282  size_t operator()(const smc::units::Unit &x) const
283  {
284  using type = typename std::underlying_type<smc::units::Unit>::type;
285  return std::hash<type>()(static_cast<type>(x));
286  }
287 };
288 
289 } /* namespace std */
290 
291 #endif /* MOTION_CONTROLLER_UNITS_HXX__ */
main motion-lib namespace
Definition: Client.cpp:30
value_type value
port value
Definition: Units.hpp:209
size_type size
size in bits
Definition: Units.hpp:210