| // 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 <boost/config/no_tr1/cmath.hpp> |
| #include <iosfwd> |
| #include <iomanip> |
| |
| #include <boost/io/ios_state.hpp> |
| |
| #include <boost/units/static_constant.hpp> |
| #include <boost/units/units_fwd.hpp> |
| #include <boost/units/operators.hpp> |
| |
| namespace boost { |
| |
| namespace units { |
| |
| template<class Base> |
| struct constant |
| { |
| typedef typename Base::value_type value_type; |
| operator value_type() const { return Base().value(); } |
| value_type value() const { return Base().value(); } |
| value_type uncertainty() const { return Base().uncertainty(); } |
| value_type lower_bound() const { return Base().lower_bound(); } |
| value_type upper_bound() const { return Base().upper_bound(); } |
| }; |
| |
| template<class Base> |
| struct physical_constant |
| { |
| typedef typename Base::value_type value_type; |
| operator value_type() const { return Base().value(); } |
| value_type value() const { return Base().value(); } |
| value_type uncertainty() const { return Base().uncertainty(); } |
| value_type lower_bound() const { return Base().lower_bound(); } |
| value_type upper_bound() const { return Base().upper_bound(); } |
| }; |
| |
| #define BOOST_UNITS_DEFINE_HELPER(name, symbol, template_name) \ |
| \ |
| template<class T, class Arg1, class Arg2> \ |
| struct name ## _typeof_helper<constant<T>, template_name<Arg1, Arg2> >\ |
| { \ |
| typedef typename name ## _typeof_helper<typename T::value_type, template_name<Arg1, Arg2> >::type type;\ |
| }; \ |
| \ |
| template<class T, class Arg1, class Arg2> \ |
| struct name ## _typeof_helper<template_name<Arg1, Arg2>, constant<T> >\ |
| { \ |
| typedef typename name ## _typeof_helper<template_name<Arg1, Arg2>, typename T::value_type>::type type;\ |
| }; \ |
| \ |
| template<class T, class Arg1, class Arg2> \ |
| typename name ## _typeof_helper<typename T::value_type, template_name<Arg1, Arg2> >::type \ |
| operator symbol(const constant<T>& t, const template_name<Arg1, Arg2>& u)\ |
| { \ |
| return(t.value() symbol u); \ |
| } \ |
| \ |
| template<class T, class Arg1, class Arg2> \ |
| typename name ## _typeof_helper<template_name<Arg1, Arg2>, typename T::value_type>::type \ |
| operator symbol(const template_name<Arg1, Arg2>& u, const constant<T>& 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<class T1, class T2> \ |
| struct name ## _typeof_helper<constant<T1>, constant<T2> > \ |
| { \ |
| typedef typename name ## _typeof_helper<typename T1::value_type, typename T2::value_type>::type type;\ |
| }; \ |
| \ |
| template<class T1, class T2> \ |
| typename name ## _typeof_helper<typename T1::value_type, typename T2::value_type>::type \ |
| operator symbol(const constant<T1>& t, const constant<T2>& u) \ |
| { \ |
| return(t.value() symbol u.value()); \ |
| } \ |
| \ |
| template<class T1, class T2> \ |
| struct name ## _typeof_helper<constant<T1>, T2> \ |
| { \ |
| typedef typename name ## _typeof_helper<typename T1::value_type, T2>::type type;\ |
| }; \ |
| \ |
| template<class T1, class T2> \ |
| struct name ## _typeof_helper<T1, constant<T2> > \ |
| { \ |
| typedef typename name ## _typeof_helper<T1, typename T2::value_type>::type type;\ |
| }; \ |
| \ |
| template<class T1, class T2> \ |
| typename name ## _typeof_helper<typename T1::value_type, T2>::type \ |
| operator symbol(const constant<T1>& t, const T2& u) \ |
| { \ |
| return(t.value() symbol u); \ |
| } \ |
| \ |
| template<class T1, class T2> \ |
| typename name ## _typeof_helper<T1, typename T2::value_type>::type \ |
| operator symbol(const T1& t, const constant<T2>& 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_PHYSICAL_CONSTANT(name, type, value_, uncertainty_) \ |
| struct name ## _t { \ |
| typedef type value_type; \ |
| 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_; } \ |
| }; \ |
| BOOST_UNITS_STATIC_CONSTANT(name, boost::units::constant<boost::units::physical_constant<name ## _t> >) = { } |
| |
| // stream output |
| template<class Char, class Traits, class Y> |
| inline |
| std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const physical_constant<Y>& 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<long>(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<class Char, class Traits, class Y> |
| inline |
| std::basic_ostream<Char,Traits>& operator<<(std::basic_ostream<Char,Traits>& os,const constant<Y>&) |
| { |
| os << Y(); |
| return os; |
| } |
| |
| } // namespace units |
| |
| } // namespace boost |
| |
| #endif // BOOST_UNITS_CONSTANTS_HPP |