// Boost.Units - A C++ library for zero-overhead dimensional analysis and // unit/quantity manipulation and conversion // // Copyright (C) 2003-2008 Matthias Christian Schabel // Copyright (C) 2008 Steven Watanabe // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_UNITS_MEASUREMENT_HPP #define BOOST_UNITS_MEASUREMENT_HPP #include #include #include #include #include #include namespace boost { namespace units { namespace sqr_namespace /**/ { template constexpr Y sqr(Y val) { return val*val; } } // namespace using sqr_namespace::sqr; template class measurement { public: typedef measurement this_type; typedef Y value_type; constexpr measurement(const value_type& val = value_type(), const value_type& err = value_type()) : value_(val), uncertainty_(std::abs(err)) { } constexpr measurement(const this_type& source) : value_(source.value_), uncertainty_(source.uncertainty_) { } //~measurement() { } constexpr this_type& operator=(const this_type& source) { if (this == &source) return *this; value_ = source.value_; uncertainty_ = source.uncertainty_; return *this; } constexpr operator value_type() const { return value_; } constexpr value_type value() const { return value_; } constexpr value_type uncertainty() const { return uncertainty_; } constexpr value_type lower_bound() const { return value_-uncertainty_; } constexpr value_type upper_bound() const { return value_+uncertainty_; } constexpr this_type& operator+=(const value_type& val) { value_ += val; return *this; } constexpr this_type& operator-=(const value_type& val) { value_ -= val; return *this; } constexpr this_type& operator*=(const value_type& val) { value_ *= val; uncertainty_ *= val; return *this; } constexpr this_type& operator/=(const value_type& val) { value_ /= val; uncertainty_ /= val; return *this; } constexpr this_type& operator+=(const this_type& /*source*/); constexpr this_type& operator-=(const this_type& /*source*/); constexpr this_type& operator*=(const this_type& /*source*/); constexpr this_type& operator/=(const this_type& /*source*/); private: value_type value_, uncertainty_; }; } } #if BOOST_UNITS_HAS_BOOST_TYPEOF BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::measurement, 1) #endif namespace boost { namespace units { template inline constexpr measurement& measurement::operator+=(const this_type& source) { uncertainty_ = std::sqrt(sqr(uncertainty_)+sqr(source.uncertainty_)); value_ += source.value_; return *this; } template inline constexpr measurement& measurement::operator-=(const this_type& source) { uncertainty_ = std::sqrt(sqr(uncertainty_)+sqr(source.uncertainty_)); value_ -= source.value_; return *this; } template inline constexpr measurement& measurement::operator*=(const this_type& source) { uncertainty_ = (value_*source.value_)* std::sqrt(sqr(uncertainty_/value_)+ sqr(source.uncertainty_/source.value_)); value_ *= source.value_; return *this; } template inline constexpr measurement& measurement::operator/=(const this_type& source) { uncertainty_ = (value_/source.value_)* std::sqrt(sqr(uncertainty_/value_)+ sqr(source.uncertainty_/source.value_)); value_ /= source.value_; return *this; } // value_type op measurement template inline constexpr measurement operator+(Y lhs,const measurement& rhs) { return (measurement(lhs,Y(0))+=rhs); } template inline constexpr measurement operator-(Y lhs,const measurement& rhs) { return (measurement(lhs,Y(0))-=rhs); } template inline constexpr measurement operator*(Y lhs,const measurement& rhs) { return (measurement(lhs,Y(0))*=rhs); } template inline constexpr measurement operator/(Y lhs,const measurement& rhs) { return (measurement(lhs,Y(0))/=rhs); } // measurement op value_type template inline constexpr measurement operator+(const measurement& lhs,Y rhs) { return (measurement(lhs)+=measurement(rhs,Y(0))); } template inline constexpr measurement operator-(const measurement& lhs,Y rhs) { return (measurement(lhs)-=measurement(rhs,Y(0))); } template inline constexpr measurement operator*(const measurement& lhs,Y rhs) { return (measurement(lhs)*=measurement(rhs,Y(0))); } template inline constexpr measurement operator/(const measurement& lhs,Y rhs) { return (measurement(lhs)/=measurement(rhs,Y(0))); } // measurement op measurement template inline constexpr measurement operator+(const measurement& lhs,const measurement& rhs) { return (measurement(lhs)+=rhs); } template inline constexpr measurement operator-(const measurement& lhs,const measurement& rhs) { return (measurement(lhs)-=rhs); } template inline constexpr measurement operator*(const measurement& lhs,const measurement& rhs) { return (measurement(lhs)*=rhs); } template inline constexpr measurement operator/(const measurement& lhs,const measurement& rhs) { return (measurement(lhs)/=rhs); } /// specialize power typeof helper template struct power_typeof_helper,static_rational > { typedef measurement< typename power_typeof_helper >::type > type; static constexpr 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 > { typedef measurement< typename root_typeof_helper >::type > type; static constexpr 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); } }; // stream output template inline 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() << ")"; return os; } } // namespace units } // namespace boost #endif // BOOST_UNITS_MEASUREMENT_HPP