Ticket #7261: measurement.hpp.diff
File measurement.hpp.diff, 9.7 KB (added by , 10 years ago) |
---|
-
.hpp
old new 1 // Boost.Units - A C++ library for zero-overhead dimensional analysis and 1 // Boost.Units - A C++ library for zero-overhead dimensional analysis and 2 2 // unit/quantity manipulation and conversion 3 3 // 4 4 // Copyright (C) 2003-2008 Matthias Christian Schabel … … 19 19 #include <boost/io/ios_state.hpp> 20 20 #include <boost/units/static_rational.hpp> 21 21 22 #include <boost/type_traits.hpp> 23 22 24 namespace boost { 23 25 24 26 namespace units { … … 35 37 36 38 template<class Y> 37 39 class measurement 38 { 40 { 39 41 public: 40 42 typedef measurement<Y> this_type; 41 43 typedef Y value_type; 42 44 43 45 measurement(const value_type& val = value_type(), 44 const value_type& err = value_type()) : 46 const value_type& err = value_type()) : 45 47 value_(val), 46 uncertainty_(std::abs(err)) 48 uncertainty_(std::abs(err)) 47 49 { } 48 49 measurement(const this_type& source) : 50 51 measurement(const this_type& source) : 50 52 value_(source.value_), 51 uncertainty_(source.uncertainty_) 53 uncertainty_(source.uncertainty_) 52 54 { } 53 55 54 56 //~measurement() { } 55 57 56 58 this_type& operator=(const this_type& source) 57 59 { 58 60 if (this == &source) return *this; 59 61 60 62 value_ = source.value_; 61 63 uncertainty_ = source.uncertainty_; 62 64 63 65 return *this; 64 66 } 65 67 66 68 operator value_type() const { return value_; } 67 69 68 70 value_type value() const { return value_; } 69 71 value_type uncertainty() const { return uncertainty_; } 70 72 value_type lower_bound() const { return value_-uncertainty_; } 71 73 value_type upper_bound() const { return value_+uncertainty_; } 72 73 this_type& operator+=(const value_type& val) 74 { 75 value_ += val; 76 return *this; 74 75 this_type& operator+=(const value_type& val) 76 { 77 value_ += val; 78 return *this; 77 79 } 78 79 this_type& operator-=(const value_type& val) 80 { 81 value_ -= val; 82 return *this; 80 81 this_type& operator-=(const value_type& val) 82 { 83 value_ -= val; 84 return *this; 83 85 } 84 85 this_type& operator*=(const value_type& val) 86 { 87 value_ *= val; 88 uncertainty_ *= val; 89 return *this; 86 87 this_type& operator*=(const value_type& val) 88 { 89 value_ *= val; 90 uncertainty_ *= val; 91 return *this; 90 92 } 91 92 this_type& operator/=(const value_type& val) 93 { 94 value_ /= val; 95 uncertainty_ /= val; 96 return *this; 93 94 this_type& operator/=(const value_type& val) 95 { 96 value_ /= val; 97 uncertainty_ /= val; 98 return *this; 97 99 } 98 100 99 101 this_type& operator+=(const this_type& /*source*/); 100 this_type& operator-=(const this_type& /*source*/); 101 this_type& operator*=(const this_type& /*source*/); 102 this_type& operator-=(const this_type& /*source*/); 103 this_type& operator*=(const this_type& /*source*/); 102 104 this_type& operator/=(const this_type& /*source*/); 103 105 106 107 104 108 private: 105 109 value_type value_, 106 110 uncertainty_; 107 }; 111 }; // class measurement 108 112 109 } 113 } // namespace units 114 } // namespace boost 110 115 111 }112 113 116 #if BOOST_UNITS_HAS_BOOST_TYPEOF 114 115 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::measurement, 1) 116 117 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::measurement, 1) 117 118 #endif 118 119 119 120 namespace boost { 120 121 121 namespace units { 122 122 123 123 template<class Y> … … 127 127 { 128 128 uncertainty_ = std::sqrt(sqr(uncertainty_)+sqr(source.uncertainty_)); 129 129 value_ += source.value_; 130 130 131 131 return *this; 132 132 } 133 133 … … 138 138 { 139 139 uncertainty_ = std::sqrt(sqr(uncertainty_)+sqr(source.uncertainty_)); 140 140 value_ -= source.value_; 141 141 142 142 return *this; 143 143 } 144 144 … … 151 151 std::sqrt(sqr(uncertainty_/value_)+ 152 152 sqr(source.uncertainty_/source.value_)); 153 153 value_ *= source.value_; 154 154 155 155 return *this; 156 156 } 157 157 … … 164 164 std::sqrt(sqr(uncertainty_/value_)+ 165 165 sqr(source.uncertainty_/source.value_)); 166 166 value_ /= source.value_; 167 167 168 168 return *this; 169 169 } 170 170 … … 268 268 } 269 269 270 270 /// specialize power typeof helper 271 template<class Y,long N,long D> 271 template<class Y,long N,long D> 272 272 struct power_typeof_helper<measurement<Y>,static_rational<N,D> > 273 { 273 { 274 274 typedef measurement< 275 275 typename power_typeof_helper<Y,static_rational<N,D> >::type 276 > type; 277 278 static type value(const measurement<Y>& x) 279 { 276 > type; 277 278 static type value(const measurement<Y>& x) 279 { 280 280 const static_rational<N,D> rat; 281 281 282 282 const Y m = Y(rat.numerator())/Y(rat.denominator()), 283 283 newval = std::pow(x.value(),m), 284 284 err = newval*std::sqrt(std::pow(m*x.uncertainty()/x.value(),2)); 285 285 286 286 return type(newval,err); 287 287 } 288 288 }; 289 289 290 290 /// specialize root typeof helper 291 template<class Y,long N,long D> 292 struct root_typeof_helper<measurement<Y>,static_rational<N,D> > 293 { 291 template<class Y,long N,long D> 292 struct root_typeof_helper<measurement<Y>,static_rational<N,D> > 293 { 294 294 typedef measurement< 295 295 typename root_typeof_helper<Y,static_rational<N,D> >::type 296 > type; 297 298 static type value(const measurement<Y>& x) 299 { 296 > type; 297 298 static type value(const measurement<Y>& x) 299 { 300 300 const static_rational<N,D> rat; 301 301 302 302 const Y m = Y(rat.denominator())/Y(rat.numerator()), 303 303 newval = std::pow(x.value(),m), 304 304 err = newval*std::sqrt(std::pow(m*x.uncertainty()/x.value(),2)); 305 305 306 306 return type(newval,err); 307 307 } 308 308 }; … … 310 310 // stream output 311 311 template<class Y> 312 312 inline 313 std::ostream& operator<<(std::ostream& os, const measurement<Y>& val)313 std::ostream& operator<<(std::ostream& os, const measurement<Y>& val) 314 314 { 315 315 boost::io::ios_precision_saver precision_saver(os); 316 316 boost::io::ios_flags_saver flags_saver(os); 317 318 os << val.value() << "(+/-" << val.uncertainty() << ")"; 319 317 std::streamsize w = os.width(); 318 if (w > 0) 319 { // Need to output both as one string to avoid disrupting column width. 320 std::ostringstream oss; 321 oss << val.value() << "(+/-" << val.uncertainty() << ")"; 322 os.width(w); 323 os << oss.str(); 324 } 325 else 326 { // Output direct to os. 327 os << val.value() << "(+/-" << val.uncertainty() << ")"; 328 } 320 329 return os; 321 330 } 322 331 332 // Specialization of autoprefix_norm for UDT boost::units::measurement<Y> 333 // See io.hpp. 334 335 // Note that autoprefix_norm_impl is in the boost::units namespace, 336 // but autoprefix_norm being specialized is in the UDT namespace (here measd). 337 // If the UDT is parameterized for floating-point type (FPT), as the 338 // example measurement, then its type can be used as a template parameter 339 // to autoprefix_norm_impl, but if not then double or other FPT is needed. 340 // This type *must* be convertible to double. 341 // If this may involve loss of precision then a warning will be issued. 342 /* 343 344 using boost::units::measd; 345 using boost::units::autoprefix_norm_impl; 346 347 autoprefix_norm_impl<measd, true>::type 348 autoprefix_norm(const measd & arg) 349 { 350 return autoprefix_norm_impl<double, true>::call(arg); 351 } 352 // Specialization of autoprefix_norm for UDT boost::units::measurement<float> 353 // Warns "conversion from 'long double' to 'double', possible loss of data" 354 autoprefix_norm_impl<boost::units::measurement<float>, true>::type 355 autoprefix_norm(const boost::units::measurement<float> & arg) 356 { 357 return autoprefix_norm_impl<double, true>::call(arg); // double or float (long double warns of loss) 358 } 359 360 // Specialization of autoprefix_norm for UDT boost::units::measurement<double> 361 // Warns "conversion from 'long double' to 'double', possible loss of data" 362 autoprefix_norm_impl<double, true>::type 363 autoprefix_norm(const boost::units::measurement<double> & arg) 364 { 365 return autoprefix_norm_impl<double, true>::call(arg); // double or float (long double warns of loss) 366 } 367 368 // This specialization is required to get autoprefix to work with this class. 369 //template<class Y> 370 //typename autoprefix_norm_impl<boost::units::measurement<Y>, true>::type 371 //autoprefix_norm(const boost::units::measurement<Y> & arg) 372 //{ 373 // return autoprefix_norm_impl<double, true>::call(arg); 374 //} 375 */ 376 377 using boost::units::autoprefix_norm_impl; 378 using boost::units::measurement; // Might be in another namespace? 379 380 template<class Y> 381 typename autoprefix_norm_impl<measurement<Y>, true>::type 382 autoprefix_norm(const measurement<Y> & arg) 383 { 384 // If measurement was not parameterized on floating-point type, might use 385 // `return autoprefix_norm_impl<double, true>::call(arg);` 386 // but must be conertible to `double`. 387 return autoprefix_norm_impl<Y, true>::call(arg); 388 } 389 390 323 391 } // namespace units 324 325 392 } // namespace boost 326 393 327 394 #endif // BOOST_UNITS_MEASUREMENT_HPP