• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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