1 // 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
22 namespace boost {
23
24 namespace units {
25
26 namespace sqr_namespace /**/ {
27
28 template<class Y>
29 constexpr
sqr(Y val)30 Y sqr(Y val)
31 { return val*val; }
32
33 } // namespace
34
35 using sqr_namespace::sqr;
36
37 template<class Y>
38 class measurement
39 {
40 public:
41 typedef measurement<Y> this_type;
42 typedef Y value_type;
43
measurement(const value_type & val=value_type (),const value_type & err=value_type ())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
measurement(const this_type & source)50 constexpr measurement(const this_type& source) :
51 value_(source.value_),
52 uncertainty_(source.uncertainty_)
53 { }
54
55 //~measurement() { }
56
operator =(const this_type & source)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
operator value_type() const67 constexpr operator value_type() const { return value_; }
68
value() const69 constexpr value_type value() const { return value_; }
uncertainty() const70 constexpr value_type uncertainty() const { return uncertainty_; }
lower_bound() const71 constexpr value_type lower_bound() const { return value_-uncertainty_; }
upper_bound() const72 constexpr value_type upper_bound() const { return value_+uncertainty_; }
73
operator +=(const value_type & val)74 constexpr this_type& operator+=(const value_type& val)
75 {
76 value_ += val;
77 return *this;
78 }
79
operator -=(const value_type & val)80 constexpr this_type& operator-=(const value_type& val)
81 {
82 value_ -= val;
83 return *this;
84 }
85
operator *=(const value_type & val)86 constexpr this_type& operator*=(const value_type& val)
87 {
88 value_ *= val;
89 uncertainty_ *= val;
90 return *this;
91 }
92
operator /=(const value_type & val)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
116 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::measurement, 1)
117
118 #endif
119
120 namespace boost {
121
122 namespace units {
123
124 template<class Y>
125 inline
126 constexpr
127 measurement<Y>&
operator +=(const this_type & source)128 measurement<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
136 template<class Y>
137 inline
138 constexpr
139 measurement<Y>&
operator -=(const this_type & source)140 measurement<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
148 template<class Y>
149 inline
150 constexpr
151 measurement<Y>&
operator *=(const this_type & source)152 measurement<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
162 template<class Y>
163 inline
164 constexpr
165 measurement<Y>&
operator /=(const this_type & source)166 measurement<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
177 template<class Y>
178 inline
179 constexpr
180 measurement<Y>
operator +(Y lhs,const measurement<Y> & rhs)181 operator+(Y lhs,const measurement<Y>& rhs)
182 {
183 return (measurement<Y>(lhs,Y(0))+=rhs);
184 }
185
186 template<class Y>
187 inline
188 constexpr
189 measurement<Y>
operator -(Y lhs,const measurement<Y> & rhs)190 operator-(Y lhs,const measurement<Y>& rhs)
191 {
192 return (measurement<Y>(lhs,Y(0))-=rhs);
193 }
194
195 template<class Y>
196 inline
197 constexpr
198 measurement<Y>
operator *(Y lhs,const measurement<Y> & rhs)199 operator*(Y lhs,const measurement<Y>& rhs)
200 {
201 return (measurement<Y>(lhs,Y(0))*=rhs);
202 }
203
204 template<class Y>
205 inline
206 constexpr
207 measurement<Y>
operator /(Y lhs,const measurement<Y> & rhs)208 operator/(Y lhs,const measurement<Y>& rhs)
209 {
210 return (measurement<Y>(lhs,Y(0))/=rhs);
211 }
212
213 // measurement op value_type
214 template<class Y>
215 inline
216 constexpr
217 measurement<Y>
operator +(const measurement<Y> & lhs,Y rhs)218 operator+(const measurement<Y>& lhs,Y rhs)
219 {
220 return (measurement<Y>(lhs)+=measurement<Y>(rhs,Y(0)));
221 }
222
223 template<class Y>
224 inline
225 constexpr
226 measurement<Y>
operator -(const measurement<Y> & lhs,Y rhs)227 operator-(const measurement<Y>& lhs,Y rhs)
228 {
229 return (measurement<Y>(lhs)-=measurement<Y>(rhs,Y(0)));
230 }
231
232 template<class Y>
233 inline
234 constexpr
235 measurement<Y>
operator *(const measurement<Y> & lhs,Y rhs)236 operator*(const measurement<Y>& lhs,Y rhs)
237 {
238 return (measurement<Y>(lhs)*=measurement<Y>(rhs,Y(0)));
239 }
240
241 template<class Y>
242 inline
243 constexpr
244 measurement<Y>
operator /(const measurement<Y> & lhs,Y rhs)245 operator/(const measurement<Y>& lhs,Y rhs)
246 {
247 return (measurement<Y>(lhs)/=measurement<Y>(rhs,Y(0)));
248 }
249
250 // measurement op measurement
251 template<class Y>
252 inline
253 constexpr
254 measurement<Y>
operator +(const measurement<Y> & lhs,const measurement<Y> & rhs)255 operator+(const measurement<Y>& lhs,const measurement<Y>& rhs)
256 {
257 return (measurement<Y>(lhs)+=rhs);
258 }
259
260 template<class Y>
261 inline
262 constexpr
263 measurement<Y>
operator -(const measurement<Y> & lhs,const measurement<Y> & rhs)264 operator-(const measurement<Y>& lhs,const measurement<Y>& rhs)
265 {
266 return (measurement<Y>(lhs)-=rhs);
267 }
268
269 template<class Y>
270 inline
271 constexpr
272 measurement<Y>
operator *(const measurement<Y> & lhs,const measurement<Y> & rhs)273 operator*(const measurement<Y>& lhs,const measurement<Y>& rhs)
274 {
275 return (measurement<Y>(lhs)*=rhs);
276 }
277
278 template<class Y>
279 inline
280 constexpr
281 measurement<Y>
operator /(const measurement<Y> & lhs,const measurement<Y> & rhs)282 operator/(const measurement<Y>& lhs,const measurement<Y>& rhs)
283 {
284 return (measurement<Y>(lhs)/=rhs);
285 }
286
287 /// specialize power typeof helper
288 template<class Y,long N,long D>
289 struct 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
valueboost::units::power_typeof_helper295 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
308 template<class Y,long N,long D>
309 struct 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
valueboost::units::root_typeof_helper315 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
328 template<class Y>
329 inline
operator <<(std::ostream & os,const measurement<Y> & val)330 std::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
345