--- C:/Users/Paul/AppData/Local/Temp/measurement.hpp-revBASE.svn000.tmp.hpp Sat Jan 15 08:11:51 2011 +++ I:/boost-trunk/libs/units/example/measurement.hpp Fri Aug 17 15:10:44 2012 @@ -1,4 +1,4 @@ -// Boost.Units - A C++ library for zero-overhead dimensional analysis and +// Boost.Units - A C++ library for zero-overhead dimensional analysis and // unit/quantity manipulation and conversion // // Copyright (C) 2003-2008 Matthias Christian Schabel @@ -19,6 +19,8 @@ #include #include +#include + namespace boost { namespace units { @@ -35,89 +37,87 @@ template class measurement -{ +{ public: typedef measurement this_type; typedef Y value_type; - + measurement(const value_type& val = value_type(), - const value_type& err = value_type()) : + const value_type& err = value_type()) : value_(val), - uncertainty_(std::abs(err)) + uncertainty_(std::abs(err)) { } - - measurement(const this_type& source) : + + measurement(const this_type& source) : value_(source.value_), - uncertainty_(source.uncertainty_) + uncertainty_(source.uncertainty_) { } - + //~measurement() { } - + this_type& operator=(const this_type& source) { if (this == &source) return *this; - + value_ = source.value_; uncertainty_ = source.uncertainty_; - + return *this; } - + operator value_type() const { return value_; } - + value_type value() const { return value_; } value_type uncertainty() const { return uncertainty_; } value_type lower_bound() const { return value_-uncertainty_; } value_type upper_bound() const { return value_+uncertainty_; } - - this_type& operator+=(const value_type& val) - { - value_ += val; - return *this; + + this_type& operator+=(const value_type& val) + { + value_ += val; + return *this; } - - this_type& operator-=(const value_type& val) - { - value_ -= val; - return *this; + + this_type& operator-=(const value_type& val) + { + value_ -= val; + return *this; } - - this_type& operator*=(const value_type& val) - { - value_ *= val; - uncertainty_ *= val; - return *this; + + this_type& operator*=(const value_type& val) + { + value_ *= val; + uncertainty_ *= val; + return *this; } - - this_type& operator/=(const value_type& val) - { - value_ /= val; - uncertainty_ /= val; - return *this; + + this_type& operator/=(const value_type& val) + { + value_ /= val; + uncertainty_ /= val; + return *this; } - + this_type& operator+=(const this_type& /*source*/); - this_type& operator-=(const this_type& /*source*/); - this_type& operator*=(const this_type& /*source*/); + this_type& operator-=(const this_type& /*source*/); + this_type& operator*=(const this_type& /*source*/); this_type& operator/=(const this_type& /*source*/); + + private: value_type value_, uncertainty_; -}; +}; // class measurement -} +} // namespace units +} // namespace boost -} - #if BOOST_UNITS_HAS_BOOST_TYPEOF - -BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::measurement, 1) - + BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::measurement, 1) #endif namespace boost { - namespace units { template @@ -127,7 +127,7 @@ { uncertainty_ = std::sqrt(sqr(uncertainty_)+sqr(source.uncertainty_)); value_ += source.value_; - + return *this; } @@ -138,7 +138,7 @@ { uncertainty_ = std::sqrt(sqr(uncertainty_)+sqr(source.uncertainty_)); value_ -= source.value_; - + return *this; } @@ -151,7 +151,7 @@ std::sqrt(sqr(uncertainty_/value_)+ sqr(source.uncertainty_/source.value_)); value_ *= source.value_; - + return *this; } @@ -164,7 +164,7 @@ std::sqrt(sqr(uncertainty_/value_)+ sqr(source.uncertainty_/source.value_)); value_ /= source.value_; - + return *this; } @@ -268,41 +268,41 @@ } /// specialize power typeof helper -template +template struct power_typeof_helper,static_rational > -{ +{ typedef measurement< typename power_typeof_helper >::type - > type; - - static type value(const measurement& x) - { + > type; + + static type value(const measurement& x) + { const static_rational rat; const Y m = Y(rat.numerator())/Y(rat.denominator()), newval = std::pow(x.value(),m), err = newval*std::sqrt(std::pow(m*x.uncertainty()/x.value(),2)); - + return type(newval,err); } }; /// specialize root typeof helper -template -struct root_typeof_helper,static_rational > -{ +template +struct root_typeof_helper,static_rational > +{ typedef measurement< typename root_typeof_helper >::type - > type; - - static type value(const measurement& x) - { + > type; + + static type value(const measurement& x) + { const static_rational rat; const Y m = Y(rat.denominator())/Y(rat.numerator()), newval = std::pow(x.value(),m), err = newval*std::sqrt(std::pow(m*x.uncertainty()/x.value(),2)); - + return type(newval,err); } }; @@ -310,18 +310,85 @@ // stream output template inline -std::ostream& operator<<(std::ostream& os,const measurement& val) +std::ostream& operator<<(std::ostream& os, const measurement& val) { boost::io::ios_precision_saver precision_saver(os); boost::io::ios_flags_saver flags_saver(os); - - os << val.value() << "(+/-" << val.uncertainty() << ")"; - + std::streamsize w = os.width(); + if (w > 0) + { // Need to output both as one string to avoid disrupting column width. + std::ostringstream oss; + oss << val.value() << "(+/-" << val.uncertainty() << ")"; + os.width(w); + os << oss.str(); + } + else + { // Output direct to os. + os << val.value() << "(+/-" << val.uncertainty() << ")"; + } return os; } +// Specialization of autoprefix_norm for UDT boost::units::measurement +// See io.hpp. + +// Note that autoprefix_norm_impl is in the boost::units namespace, +// but autoprefix_norm being specialized is in the UDT namespace (here measd). +// If the UDT is parameterized for floating-point type (FPT), as the +// example measurement, then its type can be used as a template parameter +// to autoprefix_norm_impl, but if not then double or other FPT is needed. +// This type *must* be convertible to double. +// If this may involve loss of precision then a warning will be issued. +/* + +using boost::units::measd; +using boost::units::autoprefix_norm_impl; + +autoprefix_norm_impl::type +autoprefix_norm(const measd & arg) +{ + return autoprefix_norm_impl::call(arg); +} +// Specialization of autoprefix_norm for UDT boost::units::measurement +// Warns "conversion from 'long double' to 'double', possible loss of data" +autoprefix_norm_impl, true>::type +autoprefix_norm(const boost::units::measurement & arg) +{ + return autoprefix_norm_impl::call(arg); // double or float (long double warns of loss) +} + +// Specialization of autoprefix_norm for UDT boost::units::measurement +// Warns "conversion from 'long double' to 'double', possible loss of data" +autoprefix_norm_impl::type +autoprefix_norm(const boost::units::measurement & arg) +{ + return autoprefix_norm_impl::call(arg); // double or float (long double warns of loss) +} + +// This specialization is required to get autoprefix to work with this class. +//template +//typename autoprefix_norm_impl, true>::type +//autoprefix_norm(const boost::units::measurement & arg) +//{ +// return autoprefix_norm_impl::call(arg); +//} +*/ + +using boost::units::autoprefix_norm_impl; +using boost::units::measurement; // Might be in another namespace? + +template +typename autoprefix_norm_impl, true>::type +autoprefix_norm(const measurement & arg) +{ + // If measurement was not parameterized on floating-point type, might use + // `return autoprefix_norm_impl::call(arg);` + // but must be conertible to `double`. + return autoprefix_norm_impl::call(arg); +} + + } // namespace units - } // namespace boost #endif // BOOST_UNITS_MEASUREMENT_HPP