// 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_CONSTANTS_HPP #define BOOST_UNITS_CONSTANTS_HPP #include #include #include #include #include #include #include #include #include namespace boost { namespace units { template struct constant { typedef typename Base::value_type value_type; BOOST_CONSTEXPR operator value_type() const { return Base().value(); } BOOST_CONSTEXPR value_type value() const { return Base().value(); } BOOST_CONSTEXPR value_type uncertainty() const { return Base().uncertainty(); } BOOST_CONSTEXPR value_type lower_bound() const { return Base().lower_bound(); } BOOST_CONSTEXPR value_type upper_bound() const { return Base().upper_bound(); } }; template struct physical_constant { typedef typename Base::value_type value_type; BOOST_CONSTEXPR operator value_type() const { return Base().value(); } BOOST_CONSTEXPR value_type value() const { return Base().value(); } BOOST_CONSTEXPR value_type uncertainty() const { return Base().uncertainty(); } BOOST_CONSTEXPR value_type lower_bound() const { return Base().lower_bound(); } BOOST_CONSTEXPR value_type upper_bound() const { return Base().upper_bound(); } }; #define BOOST_UNITS_DEFINE_HELPER(name, symbol, template_name) \ \ template \ struct name ## _typeof_helper, template_name >\ { \ typedef typename name ## _typeof_helper >::type type;\ }; \ \ template \ struct name ## _typeof_helper, constant >\ { \ typedef typename name ## _typeof_helper, typename T::value_type>::type type;\ }; \ \ template \ BOOST_CONSTEXPR \ typename name ## _typeof_helper >::type \ operator symbol(const constant& t, const template_name& u)\ { \ return(t.value() symbol u); \ } \ \ template \ BOOST_CONSTEXPR \ typename name ## _typeof_helper, typename T::value_type>::type \ operator symbol(const template_name& u, const constant& t)\ { \ return(u symbol t.value()); \ } BOOST_UNITS_DEFINE_HELPER(add, +, unit) BOOST_UNITS_DEFINE_HELPER(add, +, quantity) BOOST_UNITS_DEFINE_HELPER(subtract, -, unit) BOOST_UNITS_DEFINE_HELPER(subtract, -, quantity) BOOST_UNITS_DEFINE_HELPER(multiply, *, unit) BOOST_UNITS_DEFINE_HELPER(multiply, *, quantity) BOOST_UNITS_DEFINE_HELPER(divide, /, unit) BOOST_UNITS_DEFINE_HELPER(divide, /, quantity) #undef BOOST_UNITS_DEFINE_HELPER #define BOOST_UNITS_DEFINE_HELPER(name, symbol) \ \ template \ struct name ## _typeof_helper, constant > \ { \ typedef typename name ## _typeof_helper::type type;\ }; \ \ template \ BOOST_CONSTEXPR \ typename name ## _typeof_helper::type \ operator symbol(const constant& t, const constant& u) \ { \ return(t.value() symbol u.value()); \ } \ \ template \ struct name ## _typeof_helper, T2> \ { \ typedef typename name ## _typeof_helper::type type;\ }; \ \ template \ struct name ## _typeof_helper > \ { \ typedef typename name ## _typeof_helper::type type;\ }; \ \ template \ BOOST_CONSTEXPR \ typename name ## _typeof_helper::type \ operator symbol(const constant& t, const T2& u) \ { \ return(t.value() symbol u); \ } \ \ template \ BOOST_CONSTEXPR \ typename name ## _typeof_helper::type \ operator symbol(const T1& t, const constant& u) \ { \ return(t symbol u.value()); \ } BOOST_UNITS_DEFINE_HELPER(add, +) BOOST_UNITS_DEFINE_HELPER(subtract, -) BOOST_UNITS_DEFINE_HELPER(multiply, *) BOOST_UNITS_DEFINE_HELPER(divide, /) #undef BOOST_UNITS_DEFINE_HELPER #define BOOST_UNITS_DEFINE_HELPER(name, symbol) \ \ template \ struct name ## _typeof_helper, one> \ { \ typedef typename name ## _typeof_helper::type type;\ }; \ \ template \ struct name ## _typeof_helper > \ { \ typedef typename name ## _typeof_helper::type type;\ }; \ \ template \ BOOST_CONSTEXPR \ typename name ## _typeof_helper::type \ operator symbol(const constant& t, const one& u) \ { \ return(t.value() symbol u); \ } \ \ template \ BOOST_CONSTEXPR \ typename name ## _typeof_helper::type \ operator symbol(const one& t, const constant& u) \ { \ return(t symbol u.value()); \ } BOOST_UNITS_DEFINE_HELPER(multiply, *) BOOST_UNITS_DEFINE_HELPER(divide, /) #undef BOOST_UNITS_DEFINE_HELPER template struct power_typeof_helper, static_rational > { typedef power_typeof_helper > base; typedef typename base::type type; static BOOST_CONSTEXPR type value(const constant& arg) { return base::value(arg.value()); } }; #define BOOST_UNITS_DEFINE_HELPER(name, symbol) \ \ template \ struct name ## _typeof_helper > \ { \ typedef typename name ## _typeof_helper::type type;\ }; \ \ template \ BOOST_CONSTEXPR \ typename name ## _typeof_helper::type \ operator symbol(const constant& t, const one& u) \ { \ return(t.value() symbol u); \ } \ \ template \ BOOST_CONSTEXPR \ typename name ## _typeof_helper::type \ operator symbol(const one& t, const constant& u) \ { \ return(t symbol u.value()); \ } #define BOOST_UNITS_PHYSICAL_CONSTANT(name, type, value_, uncertainty_) \ struct name ## _t { \ typedef type value_type; \ BOOST_CONSTEXPR operator value_type() const { return value_; } \ BOOST_CONSTEXPR value_type value() const { return value_; } \ BOOST_CONSTEXPR value_type uncertainty() const { return uncertainty_; } \ BOOST_CONSTEXPR value_type lower_bound() const { return value_-uncertainty_; } \ BOOST_CONSTEXPR value_type upper_bound() const { return value_+uncertainty_; } \ }; \ BOOST_UNITS_STATIC_CONSTANT(name, boost::units::constant >) = { } // stream output template inline std::basic_ostream& operator<<(std::basic_ostream& os,const physical_constant& val) { boost::io::ios_precision_saver precision_saver(os); //boost::io::ios_width_saver width_saver(os); boost::io::ios_flags_saver flags_saver(os); //os << std::setw(21); typedef typename Y::value_type value_type; if (val.uncertainty() > value_type()) { const double relative_uncertainty = std::abs(val.uncertainty()/val.value()); const double exponent = std::log10(relative_uncertainty); const long digits_of_precision = static_cast(std::ceil(std::abs(exponent)))+3; // should try to replicate NIST CODATA syntax os << std::setprecision(digits_of_precision) //<< std::setw(digits_of_precision+8) //<< std::scientific << val.value(); // << long(10*(relative_uncertainty/std::pow(Y(10),Y(exponent)))); os << " (rel. unc. = " << std::setprecision(1) //<< std::setw(7) << std::scientific << relative_uncertainty << ")"; } else { os << val.value() << " (exact)"; } return os; } // stream output template inline std::basic_ostream& operator<<(std::basic_ostream& os,const constant&) { os << Y(); return os; } } // namespace units } // namespace boost #endif // BOOST_UNITS_CONSTANTS_HPP