blob: 72063023b71c17e6bb8cf48bdce82d4fda9adc49 [file] [log] [blame]
Brian Silvermana8ce4c32018-08-04 23:57:09 -07001// Boost.Units - A C++ library for zero-overhead dimensional analysis and
2// unit/quantity manipulation and conversion
3//
4// Copyright (C) 2003-2008 Matthias Christian Schabel
5// Copyright (C) 2008 Steven Watanabe
6//
7// Distributed under the Boost Software License, Version 1.0. (See
8// accompanying file LICENSE_1_0.txt or copy at
9// http://www.boost.org/LICENSE_1_0.txt)
10
11#ifndef BOOST_UNITS_MEASUREMENT_HPP
12#define BOOST_UNITS_MEASUREMENT_HPP
13
14#include <cmath>
15#include <cstdlib>
16#include <iomanip>
17#include <iostream>
18
19#include <boost/io/ios_state.hpp>
20#include <boost/units/static_rational.hpp>
21
22namespace boost {
23
24namespace units {
25
26namespace sqr_namespace /**/ {
27
28template<class Y>
29constexpr
30Y sqr(Y val)
31{ return val*val; }
32
33} // namespace
34
35using sqr_namespace::sqr;
36
37template<class Y>
38class measurement
39{
40 public:
41 typedef measurement<Y> this_type;
42 typedef Y value_type;
43
44 constexpr measurement(const value_type& val = value_type(),
45 const value_type& err = value_type()) :
46 value_(val),
47 uncertainty_(std::abs(err))
48 { }
49
50 constexpr measurement(const this_type& source) :
51 value_(source.value_),
52 uncertainty_(source.uncertainty_)
53 { }
54
55 //~measurement() { }
56
57 constexpr this_type& operator=(const this_type& source)
58 {
59 if (this == &source) return *this;
60
61 value_ = source.value_;
62 uncertainty_ = source.uncertainty_;
63
64 return *this;
65 }
66
67 constexpr operator value_type() const { return value_; }
68
69 constexpr value_type value() const { return value_; }
70 constexpr value_type uncertainty() const { return uncertainty_; }
71 constexpr value_type lower_bound() const { return value_-uncertainty_; }
72 constexpr value_type upper_bound() const { return value_+uncertainty_; }
73
74 constexpr this_type& operator+=(const value_type& val)
75 {
76 value_ += val;
77 return *this;
78 }
79
80 constexpr this_type& operator-=(const value_type& val)
81 {
82 value_ -= val;
83 return *this;
84 }
85
86 constexpr this_type& operator*=(const value_type& val)
87 {
88 value_ *= val;
89 uncertainty_ *= val;
90 return *this;
91 }
92
93 constexpr this_type& operator/=(const value_type& val)
94 {
95 value_ /= val;
96 uncertainty_ /= val;
97 return *this;
98 }
99
100 constexpr this_type& operator+=(const this_type& /*source*/);
101 constexpr this_type& operator-=(const this_type& /*source*/);
102 constexpr this_type& operator*=(const this_type& /*source*/);
103 constexpr this_type& operator/=(const this_type& /*source*/);
104
105 private:
106 value_type value_,
107 uncertainty_;
108};
109
110}
111
112}
113
114#if BOOST_UNITS_HAS_BOOST_TYPEOF
115
116BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::measurement, 1)
117
118#endif
119
120namespace boost {
121
122namespace units {
123
124template<class Y>
125inline
126constexpr
127measurement<Y>&
128measurement<Y>::operator+=(const this_type& source)
129{
130 uncertainty_ = std::sqrt(sqr(uncertainty_)+sqr(source.uncertainty_));
131 value_ += source.value_;
132
133 return *this;
134}
135
136template<class Y>
137inline
138constexpr
139measurement<Y>&
140measurement<Y>::operator-=(const this_type& source)
141{
142 uncertainty_ = std::sqrt(sqr(uncertainty_)+sqr(source.uncertainty_));
143 value_ -= source.value_;
144
145 return *this;
146}
147
148template<class Y>
149inline
150constexpr
151measurement<Y>&
152measurement<Y>::operator*=(const this_type& source)
153{
154 uncertainty_ = (value_*source.value_)*
155 std::sqrt(sqr(uncertainty_/value_)+
156 sqr(source.uncertainty_/source.value_));
157 value_ *= source.value_;
158
159 return *this;
160}
161
162template<class Y>
163inline
164constexpr
165measurement<Y>&
166measurement<Y>::operator/=(const this_type& source)
167{
168 uncertainty_ = (value_/source.value_)*
169 std::sqrt(sqr(uncertainty_/value_)+
170 sqr(source.uncertainty_/source.value_));
171 value_ /= source.value_;
172
173 return *this;
174}
175
176// value_type op measurement
177template<class Y>
178inline
179constexpr
180measurement<Y>
181operator+(Y lhs,const measurement<Y>& rhs)
182{
183 return (measurement<Y>(lhs,Y(0))+=rhs);
184}
185
186template<class Y>
187inline
188constexpr
189measurement<Y>
190operator-(Y lhs,const measurement<Y>& rhs)
191{
192 return (measurement<Y>(lhs,Y(0))-=rhs);
193}
194
195template<class Y>
196inline
197constexpr
198measurement<Y>
199operator*(Y lhs,const measurement<Y>& rhs)
200{
201 return (measurement<Y>(lhs,Y(0))*=rhs);
202}
203
204template<class Y>
205inline
206constexpr
207measurement<Y>
208operator/(Y lhs,const measurement<Y>& rhs)
209{
210 return (measurement<Y>(lhs,Y(0))/=rhs);
211}
212
213// measurement op value_type
214template<class Y>
215inline
216constexpr
217measurement<Y>
218operator+(const measurement<Y>& lhs,Y rhs)
219{
220 return (measurement<Y>(lhs)+=measurement<Y>(rhs,Y(0)));
221}
222
223template<class Y>
224inline
225constexpr
226measurement<Y>
227operator-(const measurement<Y>& lhs,Y rhs)
228{
229 return (measurement<Y>(lhs)-=measurement<Y>(rhs,Y(0)));
230}
231
232template<class Y>
233inline
234constexpr
235measurement<Y>
236operator*(const measurement<Y>& lhs,Y rhs)
237{
238 return (measurement<Y>(lhs)*=measurement<Y>(rhs,Y(0)));
239}
240
241template<class Y>
242inline
243constexpr
244measurement<Y>
245operator/(const measurement<Y>& lhs,Y rhs)
246{
247 return (measurement<Y>(lhs)/=measurement<Y>(rhs,Y(0)));
248}
249
250// measurement op measurement
251template<class Y>
252inline
253constexpr
254measurement<Y>
255operator+(const measurement<Y>& lhs,const measurement<Y>& rhs)
256{
257 return (measurement<Y>(lhs)+=rhs);
258}
259
260template<class Y>
261inline
262constexpr
263measurement<Y>
264operator-(const measurement<Y>& lhs,const measurement<Y>& rhs)
265{
266 return (measurement<Y>(lhs)-=rhs);
267}
268
269template<class Y>
270inline
271constexpr
272measurement<Y>
273operator*(const measurement<Y>& lhs,const measurement<Y>& rhs)
274{
275 return (measurement<Y>(lhs)*=rhs);
276}
277
278template<class Y>
279inline
280constexpr
281measurement<Y>
282operator/(const measurement<Y>& lhs,const measurement<Y>& rhs)
283{
284 return (measurement<Y>(lhs)/=rhs);
285}
286
287/// specialize power typeof helper
288template<class Y,long N,long D>
289struct power_typeof_helper<measurement<Y>,static_rational<N,D> >
290{
291 typedef measurement<
292 typename power_typeof_helper<Y,static_rational<N,D> >::type
293 > type;
294
295 static constexpr type value(const measurement<Y>& x)
296 {
297 const static_rational<N,D> rat;
298
299 const Y m = Y(rat.numerator())/Y(rat.denominator()),
300 newval = std::pow(x.value(),m),
301 err = newval*std::sqrt(std::pow(m*x.uncertainty()/x.value(),2));
302
303 return type(newval,err);
304 }
305};
306
307/// specialize root typeof helper
308template<class Y,long N,long D>
309struct root_typeof_helper<measurement<Y>,static_rational<N,D> >
310{
311 typedef measurement<
312 typename root_typeof_helper<Y,static_rational<N,D> >::type
313 > type;
314
315 static constexpr type value(const measurement<Y>& x)
316 {
317 const static_rational<N,D> rat;
318
319 const Y m = Y(rat.denominator())/Y(rat.numerator()),
320 newval = std::pow(x.value(),m),
321 err = newval*std::sqrt(std::pow(m*x.uncertainty()/x.value(),2));
322
323 return type(newval,err);
324 }
325};
326
327// stream output
328template<class Y>
329inline
330std::ostream& operator<<(std::ostream& os,const measurement<Y>& val)
331{
332 boost::io::ios_precision_saver precision_saver(os);
333 boost::io::ios_flags_saver flags_saver(os);
334
335 os << val.value() << "(+/-" << val.uncertainty() << ")";
336
337 return os;
338}
339
340} // namespace units
341
342} // namespace boost
343
344#endif // BOOST_UNITS_MEASUREMENT_HPP