source: rrlib_si_units/tQuantity.h @ 76:065985a2366d

17.03
Last change on this file since 76:065985a2366d was 76:065985a2366d, checked in by Max Reichardt <mreichardt@…>, 3 years ago

Merge with 14.08

File size: 15.1 KB
Line 
1//
2// You received this file as part of RRLib
3// Robotics Research Library
4//
5// Copyright (C) Finroc GbR (finroc.org)
6//
7// This program is free software; you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation; either version 2 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License along
18// with this program; if not, write to the Free Software Foundation, Inc.,
19// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20//
21//----------------------------------------------------------------------
22/*!\file    rrlib/si_units/tQuantity.h
23 *
24 * \author  Tobias Foehst
25 *
26 * \date    2010-03-15
27 *
28 * \brief Contains tQuantity
29 *
30 * \b tQuantity
31 *
32 */
33//----------------------------------------------------------------------
34#ifndef __rrlib__si_units__include_guard__
35#error Invalid include directive. Try #include "rrlib/si_units/si_units.h" instead.
36#endif
37
38#ifndef __rrlib__si_units__tQuantity_h__
39#define __rrlib__si_units__tQuantity_h__
40
41//----------------------------------------------------------------------
42// External includes (system with <>, local with "")
43//----------------------------------------------------------------------
44#include <cmath>
45#include <type_traits>
46#include <chrono>
47
48#include "rrlib/math/utilities.h"
49
50//----------------------------------------------------------------------
51// Internal includes with ""
52//----------------------------------------------------------------------
53#include "rrlib/si_units/operators/tProduct.h"
54#include "rrlib/si_units/operators/tQuotient.h"
55
56#ifdef _LIB_RRLIB_SERIALIZATION_PRESENT_
57#include "rrlib/serialization/serialization.h"
58#endif
59
60//----------------------------------------------------------------------
61// Debugging
62//----------------------------------------------------------------------
63#include <cassert>
64
65//----------------------------------------------------------------------
66// Namespace declaration
67//----------------------------------------------------------------------
68namespace rrlib
69{
70namespace si_units
71{
72
73//----------------------------------------------------------------------
74// Forward declarations / typedefs / enums
75//----------------------------------------------------------------------
76template <typename TUnit, typename TValue = double>
77class tQuantity;
78
79//----------------------------------------------------------------------
80// Class declaration
81//----------------------------------------------------------------------
82class tQuantityBase
83{};
84
85//!
86/*!
87 *
88 */
89template <int Tlength, int Tmass, int Ttime, int Telectric_current, int Ttemperature, int Tamount_of_substance, int Tluminous_intensity, typename TValue>
90class tQuantity<tSIUnit<Tlength, Tmass, Ttime, Telectric_current, Ttemperature, Tamount_of_substance, Tluminous_intensity>, TValue> : public tQuantityBase
91{
92
93//----------------------------------------------------------------------
94// Public methods and typedefs
95//----------------------------------------------------------------------
96public:
97
98  typedef tSIUnit<Tlength, Tmass, Ttime, Telectric_current, Ttemperature, Tamount_of_substance, Tluminous_intensity> tUnit;
99  typedef TValue tValue;
100
101  tQuantity()
102    : value()
103  {}
104
105  template < typename T, typename = typename std::enable_if < !std::is_base_of<tQuantityBase, T>::value, decltype(TValue(T())) >::type >
106  tQuantity(T value)
107    : value(TValue(value))
108  {}
109
110  template <typename TRep, typename TPeriod, typename = typename std::enable_if <std::is_same<tUnit, tSIUnit<0, 0, 1, 0, 0, 0, 0>>::value, TRep>::type>
111  tQuantity(std::chrono::duration<TRep, TPeriod> duration)
112    : value(std::chrono::duration<TValue>(duration).count())
113  {}
114
115  template <typename TOtherValue>
116  tQuantity(tQuantity<tUnit, TOtherValue> other)
117    : value(other.Value())
118  {}
119
120  template <typename TOtherValue>
121  tQuantity &operator= (tQuantity<tUnit, TOtherValue> other)
122  {
123    this->value = other.Value();
124    return *this;
125  }
126
127  template < typename T, typename = typename std::enable_if < !std::is_base_of<tQuantityBase, T>::value, decltype(T(TValue())) >::type >
128  explicit inline operator T() const
129  {
130    return static_cast<T>(this->value);
131  }
132
133  template <typename TRep, typename TPeriod, typename = typename std::enable_if <std::is_same<tUnit, tSIUnit<0, 0, 1, 0, 0, 0, 0>>::value, TRep>::type>
134  explicit inline operator std::chrono::duration<TRep, TPeriod>() const
135  {
136    return std::chrono::duration_cast<std::chrono::duration<TRep, TPeriod>>(std::chrono::duration<TValue>(this->value));
137  }
138
139  inline TValue Value() const
140  {
141    return this->value;
142  }
143
144  tQuantity operator += (tQuantity other)
145  {
146    this->value += other.value;
147    return *this;
148  }
149
150  tQuantity operator -= (tQuantity other)
151  {
152    this->value -= other.value;
153    return *this;
154  }
155
156//----------------------------------------------------------------------
157// Private fields and methods
158//----------------------------------------------------------------------
159private:
160
161  TValue value;
162
163};
164
165//----------------------------------------------------------------------
166// Unary minus
167//----------------------------------------------------------------------
168template <typename TUnit, typename TValue>
169tQuantity<TUnit, TValue> operator - (tQuantity<TUnit, TValue> value)
170{
171  return tQuantity<TUnit, TValue>(-value.Value());
172}
173
174//----------------------------------------------------------------------
175// Addition
176//----------------------------------------------------------------------
177template <typename TUnit, typename TLeftValue, typename TRightValue>
178tQuantity < TUnit, decltype(TLeftValue() + TRightValue()) > operator + (tQuantity<TUnit, TLeftValue> left, tQuantity<TUnit, TRightValue> right)
179{
180  tQuantity < TUnit, decltype(TLeftValue() + TRightValue()) > result(left);
181  result += right;
182  return result;
183}
184
185template <typename TValue, typename TRep, typename TPeriod>
186tQuantity<tSIUnit<0, 0, 1, 0, 0, 0, 0>, TValue> operator + (tQuantity<tSIUnit<0, 0, 1, 0, 0, 0, 0>, TValue> time, std::chrono::duration<TRep, TPeriod> duration)
187{
188  return time + tQuantity<tSIUnit<0, 0, 1, 0, 0, 0, 0>, double>(std::chrono::duration<double>(duration));
189}
190template <typename TValue, typename TRep, typename TPeriod>
191tQuantity<tSIUnit<0, 0, 1, 0, 0, 0, 0>, TValue> operator + (std::chrono::duration<TRep, TPeriod> duration, tQuantity<tSIUnit<0, 0, 1, 0, 0, 0, 0>, TValue> time)
192{
193  return time + duration;
194}
195
196//----------------------------------------------------------------------
197// Subtraction
198//----------------------------------------------------------------------
199template <typename TUnit, typename TLeftValue, typename TRightValue>
200tQuantity < TUnit, decltype(TLeftValue() - TRightValue()) > operator - (tQuantity<TUnit, TLeftValue> left, tQuantity<TUnit, TRightValue> right)
201{
202  tQuantity < TUnit, decltype(TLeftValue() - TRightValue()) > result(left);
203  result -= right;
204  return result;
205}
206
207template <typename TValue, typename TRep, typename TPeriod>
208tQuantity<tSIUnit<0, 0, 1, 0, 0, 0, 0>, TValue> operator - (tQuantity<tSIUnit<0, 0, 1, 0, 0, 0, 0>, TValue> time, std::chrono::duration<TRep, TPeriod> duration)
209{
210  return time - tQuantity<tSIUnit<0, 0, 1, 0, 0, 0, 0>, double>(std::chrono::duration<double>(duration));
211}
212template <typename TValue, typename TRep, typename TPeriod>
213tQuantity<tSIUnit<0, 0, 1, 0, 0, 0, 0>, TValue> operator - (std::chrono::duration<TRep, TPeriod> duration, tQuantity<tSIUnit<0, 0, 1, 0, 0, 0, 0>, TValue> time)
214{
215  return tQuantity<tSIUnit<0, 0, 1, 0, 0, 0, 0>, double>(std::chrono::duration<double>(duration)) - time;
216}
217
218//----------------------------------------------------------------------
219// Multiplication
220//----------------------------------------------------------------------
221template <typename TLeftUnit, typename TRightUnit, typename TLeftValue, typename TRightValue>
222tQuantity<typename operators::tProduct<TLeftUnit, TRightUnit>::tResult, decltype(TLeftValue() * TRightValue())> operator *(tQuantity<TLeftUnit, TLeftValue> left, tQuantity<TRightUnit, TRightValue> right)
223{
224  return tQuantity<typename operators::tProduct<TLeftUnit, TRightUnit>::tResult, decltype(TLeftValue() * TRightValue())>(left.Value() * right.Value());
225}
226
227template <typename TUnit, typename TValue, typename TScalar>
228tQuantity<TUnit, decltype(TValue() * TScalar())> operator *(tQuantity<TUnit, TValue> quantity, TScalar scalar)
229{
230  return tQuantity<TUnit, decltype(TValue() * TScalar())>(quantity.Value() * scalar);
231}
232template <typename TUnit, typename TValue, typename TScalar>
233tQuantity<TUnit, decltype(TValue() * TScalar())> operator *(TScalar scalar, tQuantity<TUnit, TValue> quantity)
234{
235  return quantity * scalar;
236}
237
238template <typename TUnit, typename TValue, typename TRep, typename TPeriod>
239tQuantity<typename operators::tProduct<TUnit, tSIUnit<0, 0, 1, 0, 0, 0, 0>>::tResult, TValue> operator *(tQuantity<TUnit, TValue> quantity, std::chrono::duration<TRep, TPeriod> duration)
240{
241  return quantity * tQuantity<tSIUnit<0, 0, 1, 0, 0, 0, 0>, double>(std::chrono::duration<double>(duration));
242}
243template <typename TUnit, typename TValue, typename TRep, typename TPeriod>
244tQuantity<typename operators::tProduct<TUnit, tSIUnit<0, 0, 1, 0, 0, 0, 0>>::tResult, TValue> operator *(std::chrono::duration<TRep, TPeriod> duration, tQuantity<TUnit, TValue> quantity)
245{
246  return quantity * duration;
247}
248
249//----------------------------------------------------------------------
250// Division
251//----------------------------------------------------------------------
252template <typename TLeftUnit, typename TRightUnit, typename TLeftValue, typename TRightValue>
253tQuantity < typename operators::tQuotient<TLeftUnit, TRightUnit>::tResult, decltype(TLeftValue() / TRightValue()) > operator / (tQuantity<TLeftUnit, TLeftValue> left, tQuantity<TRightUnit, TRightValue> right)
254{
255  return tQuantity < typename operators::tQuotient<TLeftUnit, TRightUnit>::tResult, decltype(TLeftValue() / TRightValue()) > (left.Value() / right.Value());
256}
257
258template <typename TUnit, typename TValue>
259tQuantity < TUnit, decltype(TValue() / double()) > operator /(tQuantity<TUnit, TValue> quantity, double scalar)
260{
261  return quantity / tQuantity<tSIUnit<0, 0, 0, 0, 0, 0, 0>>(scalar);
262}
263template <typename TUnit, typename TValue>
264tQuantity < typename operators::tQuotient<tSIUnit<0, 0, 0, 0, 0, 0, 0>, TUnit>::tResult, decltype(double() / TValue()) > operator /(double scalar, tQuantity<TUnit, TValue> quantity)
265{
266  return tQuantity<tSIUnit<0, 0, 0, 0, 0, 0, 0>>(scalar) / quantity;
267}
268
269template <typename TUnit, typename TValue, typename TRep, typename TPeriod>
270tQuantity<typename operators::tQuotient<TUnit, tSIUnit<0, 0, 1, 0, 0, 0, 0>>::tResult, TValue> operator /(tQuantity<TUnit, TValue> quantity, std::chrono::duration<TRep, TPeriod> duration)
271{
272  return quantity / tQuantity<tSIUnit<0, 0, 1, 0, 0, 0, 0>, double>(std::chrono::duration<double>(duration));
273}
274template <typename TUnit, typename TValue, typename TRep, typename TPeriod>
275tQuantity<typename operators::tQuotient<TUnit, tSIUnit<0, 0, 1, 0, 0, 0, 0>>::tResult, TValue> operator /(std::chrono::duration<TRep, TPeriod> duration, tQuantity<TUnit, TValue> quantity)
276{
277  return quantity / duration;
278}
279
280//----------------------------------------------------------------------
281// Comparison
282//----------------------------------------------------------------------
283template <typename TUnit, typename TLeftValue, typename TRightValue>
284const bool operator == (tQuantity<TUnit, TLeftValue> left, tQuantity<TUnit, TRightValue> right)
285{
286  return left.Value() == right.Value();
287}
288
289template <typename TUnit, typename TLeftValue, typename TRightValue>
290const bool operator != (tQuantity<TUnit, TLeftValue> left, tQuantity<TUnit, TRightValue> right)
291{
292  return !(left == right);
293}
294
295template <typename TUnit, typename TLeftValue, typename TRightValue>
296const bool operator < (tQuantity<TUnit, TLeftValue> left, tQuantity<TUnit, TRightValue> right)
297{
298  return left.Value() < right.Value();
299}
300
301template <typename TUnit, typename TLeftValue, typename TRightValue>
302const bool operator > (tQuantity<TUnit, TLeftValue> left, tQuantity<TUnit, TRightValue> right)
303{
304  return left.Value() > right.Value();
305}
306
307template <typename TUnit, typename TLeftValue, typename TRightValue>
308const bool operator <= (tQuantity<TUnit, TLeftValue> left, tQuantity<TUnit, TRightValue> right)
309{
310  return !(left > right);
311}
312
313template <typename TUnit, typename TLeftValue, typename TRightValue>
314const bool operator >= (tQuantity<TUnit, TLeftValue> left, tQuantity<TUnit, TRightValue> right)
315{
316  return !(left < right);
317}
318
319template <typename TUnit, typename TLeftValue, typename TRightValue>
320const bool IsEqual(tQuantity<TUnit, TLeftValue> a, tQuantity<TUnit, TRightValue> b, float max_error = 1.0E-6, math::tFloatComparisonMethod method = math::eFCM_ABSOLUTE_ERROR)
321{
322  return IsEqual(a.Value(), b.Value(), max_error, method);
323}
324
325//----------------------------------------------------------------------
326// Streaming
327//----------------------------------------------------------------------
328template <typename TUnit, typename TValue>
329std::ostream &operator << (std::ostream &stream, tQuantity<TUnit, TValue> quantity)
330{
331  stream << quantity.Value() << " " << TUnit();
332  return stream;
333}
334
335template <typename TUnit, typename TValue>
336std::istream &operator >> (std::istream &stream, tQuantity<TUnit, TValue>& quantity)
337{
338  TValue value = 0;
339  stream >> value;
340  std::ostringstream unit_string;
341  unit_string << TUnit();
342  internal::ReadSIUnit(stream, unit_string);
343  quantity = value;
344  return stream;
345}
346
347#ifdef _LIB_RRLIB_SERIALIZATION_PRESENT_
348
349template <typename TUnit, typename TValue>
350inline serialization::tOutputStream& operator << (serialization::tOutputStream &stream, tQuantity<TUnit, TValue> quantity)
351{
352  stream << quantity.Value();
353  return stream;
354}
355
356template <typename TUnit, typename TValue>
357inline serialization::tInputStream& operator >> (serialization::tInputStream &stream, tQuantity<TUnit, TValue> &quantity)
358{
359  TValue value;
360  stream >> value;
361  quantity = tQuantity<TUnit, TValue>(value);
362  return stream;
363}
364
365template <typename TUnit, typename TValue>
366inline serialization::tStringOutputStream &operator << (serialization::tStringOutputStream &stream, tQuantity<TUnit, TValue> quantity)
367{
368  stream.GetWrappedStringStream() << quantity;
369  return stream;
370}
371
372template <typename TUnit, typename TValue>
373inline serialization::tStringInputStream &operator >> (serialization::tStringInputStream &stream, tQuantity<TUnit, TValue> &quantity)
374{
375  TValue value;
376  stream.GetWrappedStringStream() >> value;
377  std::string symbol_string = stream.ReadWhile("/^", serialization::tStringInputStream::cWHITESPACE | serialization::tStringInputStream::cLETTER | serialization::tStringInputStream::cDIGIT, true);
378  double factor = symbol_string.length() ? tSymbolParser<TUnit>::GetFactorToBaseUnit(symbol_string) : 1;
379  quantity = tQuantity<TUnit, TValue>(static_cast<TValue>(factor * value));
380  return stream;
381}
382
383#endif
384
385//----------------------------------------------------------------------
386// End of namespace declaration
387//----------------------------------------------------------------------
388}
389}
390
391#endif
Note: See TracBrowser for help on using the repository browser.